SHOGUN
v2.0.0
|
00001 /* 00002 * This program is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 3 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * Copyright (C) 2012 Soeren Sonnenburg 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__