Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef __SGREFERENCED_DATA_H__
00010 #define __SGREFERENCED_DATA_H__
00011
00012 #include <shogun/io/SGIO.h>
00013 #include <shogun/base/Parallel.h>
00014
00015 #ifdef HAVE_PTHREAD
00016 #include <pthread.h>
00017 #endif
00018
00020 struct refcount_t
00021 {
00023 int32_t rc;
00024 #ifdef HAVE_PTHREAD
00025
00026 PTHREAD_LOCK_T lock;
00027 #endif
00028 };
00029
00030 namespace shogun
00031 {
00033 class SGReferencedData
00034 {
00035 public:
00037 SGReferencedData(bool ref_counting=true) : m_refcount(NULL)
00038 {
00039 if (ref_counting)
00040 {
00041 m_refcount = SG_CALLOC(refcount_t, 1);
00042 PTHREAD_LOCK_INIT(&m_refcount->lock);
00043 }
00044
00045 ref();
00046 }
00047
00049 SGReferencedData(const SGReferencedData &orig)
00050 : m_refcount(orig.m_refcount)
00051 {
00052 ref();
00053 }
00054
00056 SGReferencedData& operator= (const SGReferencedData &orig)
00057 {
00058 if (this == &orig)
00059 return *this;
00060
00061 unref();
00062 copy_data(orig);
00063 copy_refcount(orig);
00064 ref();
00065 return *this;
00066 }
00067
00073 virtual ~SGReferencedData()
00074 {
00075 }
00076
00081 int32_t ref_count()
00082 {
00083 if (m_refcount == NULL)
00084 return -1;
00085
00086 #ifdef HAVE_PTHREAD
00087 PTHREAD_LOCK(&m_refcount->lock);
00088 #endif
00089 int32_t c = m_refcount->rc;
00090 #ifdef HAVE_PTHREAD
00091 PTHREAD_UNLOCK(&m_refcount->lock);
00092 #endif
00093
00094 #ifdef DEBUG_SGVECTOR
00095 SG_SGCDEBUG("ref_count(): refcount %d, data %p\n", c, this);
00096 #endif
00097 return c;
00098 }
00099
00100 protected:
00102 void copy_refcount(const SGReferencedData &orig)
00103 {
00104 m_refcount=orig.m_refcount;
00105 }
00106
00111 int32_t ref()
00112 {
00113 if (m_refcount == NULL)
00114 {
00115 return -1;
00116 }
00117
00118 #ifdef HAVE_PTHREAD
00119 PTHREAD_LOCK(&m_refcount->lock);
00120 #endif
00121 int32_t c = ++(m_refcount->rc);
00122 #ifdef HAVE_PTHREAD
00123 PTHREAD_UNLOCK(&m_refcount->lock);
00124 #endif
00125 #ifdef DEBUG_SGVECTOR
00126 SG_SGCDEBUG("ref() refcount %ld data %p increased\n", c, this);
00127 #endif
00128 return c;
00129 }
00130
00136 int32_t unref()
00137 {
00138 if (m_refcount == NULL)
00139 {
00140 init_data();
00141 m_refcount=NULL;
00142 return -1;
00143 }
00144
00145 #ifdef HAVE_PTHREAD
00146 PTHREAD_LOCK(&m_refcount->lock);
00147 #endif
00148 int32_t c = --(m_refcount->rc);
00149 #ifdef HAVE_PTHREAD
00150 PTHREAD_UNLOCK(&m_refcount->lock);
00151 #endif
00152 if (c<=0)
00153 {
00154 #ifdef DEBUG_SGVECTOR
00155 SG_SGCDEBUG("unref() refcount %d data %p destroying\n", c, this);
00156 #endif
00157 free_data();
00158 #ifdef HAVE_PTHREAD
00159 PTHREAD_LOCK_DESTROY(&m_refcount->lock);
00160 #endif
00161 SG_FREE(m_refcount);
00162 m_refcount=NULL;
00163 return 0;
00164 }
00165 else
00166 {
00167 #ifdef DEBUG_SGVECTOR
00168 SG_SGCDEBUG("unref() refcount %d data %p decreased\n", c, this);
00169 #endif
00170 init_data();
00171 m_refcount=NULL;
00172 return c;
00173 }
00174 }
00175
00177 virtual void copy_data(const SGReferencedData &orig)=0;
00178
00180 virtual void init_data()=0;
00181
00183 virtual void free_data()=0;
00184
00185 private:
00186
00188 refcount_t* m_refcount;
00189 };
00190 }
00191 #endif // __SGREFERENCED_DATA_H__