summaryrefslogtreecommitdiff
path: root/src/piraha/smart_ptr.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/piraha/smart_ptr.hpp')
-rw-r--r--src/piraha/smart_ptr.hpp177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/piraha/smart_ptr.hpp b/src/piraha/smart_ptr.hpp
new file mode 100644
index 00000000..0994a821
--- /dev/null
+++ b/src/piraha/smart_ptr.hpp
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011 Steve Brandt and Philip LeBlanc
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
+////////////////////////////////////////////////////////////////////////////////
+#ifndef SMART_PTR_HPP
+#define SMART_PTR_HPP
+#include <assert.h>
+#include <vector>
+#include <iostream>
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+extern std::vector<void*> ptrs;
+
+#ifndef NDEBUG
+inline void add(std::vector<void*>& v,void *t) {
+ if(t == NULL)
+ return;
+ typedef typename std::vector<void*>::iterator iter;
+ for(iter i=v.begin();i != v.end();++i) {
+ assert(*i != t);
+ }
+ v.push_back(t);
+}
+
+inline void remove(std::vector<void*>& v,void* t) {
+ if(t == NULL)
+ return;
+ typedef typename std::vector<void*>::iterator iter;
+ for(iter i=v.begin();i != v.end();++i) {
+ if(*i == t) {
+ v.erase(i);
+ return;
+ }
+ }
+ assert(false);
+}
+#else
+inline void add(std::vector<void*>& v,void* t) {
+}
+inline void remove(std::vector<void*>& v,void* t) {
+}
+#endif
+
+template<typename T>
+class smart_ptr;
+
+template<typename T>
+class smart_ptr_guts {
+ int ref_count;
+ public:
+ T * const ptr;
+ bool array;
+ smart_ptr_guts(int rc,T *p,bool array_) : ref_count(rc), ptr(p), array(array_) {
+ if(ptr != NULL) {
+ add(ptrs,(void*)ptr);
+ }
+ }
+ ~smart_ptr_guts() {
+ if(ptr != NULL) {
+ remove(ptrs,(void*)ptr);
+ if(array)
+ delete[] ptr;
+ else
+ delete ptr;
+ }
+ }
+ void inc() {
+ ref_count++;
+ }
+ bool dec() {
+ int r = ref_count;
+ if(ref_count>0)
+ ref_count--;
+ return r==1;
+ }
+ int ref_count_() {
+ return ref_count;
+ }
+};
+
+// Count references to an object in a thread-safe
+// way using pthreads and do automatic clean up.
+template<typename T>
+class smart_ptr {
+ smart_ptr_guts<T> *guts;
+ void clean() {
+ assert(this != NULL);
+ if(guts != NULL && guts->dec()) {
+ delete guts;
+ guts = NULL;
+ }
+ }
+ public:
+ void inc() {
+ if(valid())
+ guts->inc();
+ }
+ smart_ptr(T *ptr,bool array_=false) {
+ if(ptr == NULL) {
+ guts = NULL;
+ } else {
+ guts = new smart_ptr_guts<T>(1,ptr,array_);
+ }
+ }
+ smart_ptr(const smart_ptr<T> &sm) : guts(sm.guts) {
+ if(sm.guts != NULL)
+ guts->inc();
+ }
+ smart_ptr() : guts(NULL) {}
+ ~smart_ptr() {
+ clean();
+ }
+ void operator=(T *t) {
+ clean();
+ if(t == NULL) {
+ guts = NULL;
+ } else {
+ guts = new smart_ptr_guts<T>(1,t,false);
+ }
+ }
+ void set(T *t,bool array_) {
+ clean();
+ if(t == NULL) {
+ guts = NULL;
+ } else {
+ guts = new smart_ptr_guts<T>(1,t,array_);
+ }
+ }
+ void operator=(const smart_ptr<T>& s) {
+ assert(this != NULL);
+ clean();
+ guts = s.guts;
+ if(guts != NULL)
+ guts->inc();
+ }
+ T& operator*() {
+ assert(guts != NULL);
+ return *guts->ptr;
+ }
+ T& operator[](unsigned int n) {
+ assert(guts != NULL);
+ assert(guts->array);
+ return guts->ptr[n];
+ }
+ T *operator->() const {
+ if(guts == NULL)
+ return NULL;
+ else
+ return guts->ptr;
+ }
+ T *ptr() {
+ assert(guts != NULL);
+ return guts->ptr;
+ }
+ bool valid() {
+ return guts != NULL && guts->ptr != NULL;
+ }
+ int ref_count() {
+ assert(guts != NULL);
+ return guts->ref_count_();
+ }
+ template<typename C>
+ smart_ptr<C> dup() {
+ smart_ptr<C> c;
+ c.guts = (smart_ptr_guts<C> *)guts;
+ guts->inc();
+ return c;
+ }
+ template<typename C>
+ friend class smart_ptr;
+};
+#endif