00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef MORE_GEN_MEMORY_H
00031 #define MORE_GEN_MEMORY_H
00032
00033 #include <memory>
00034 #include <stdexcept>
00035 #include <more/bits/config.h>
00036 #if HAVE_BDWGC
00037 # include <bdwgc/gc.h>
00038 # include <bdwgc/gc_cpp.h>
00039 # include <limits>
00040 #endif
00041
00042 namespace more {
00043 namespace gen {
00044
00045
00046
00047
00048 struct bad_deref
00049 : std::exception
00050 {
00051 explicit bad_deref(char const* str = 0) throw() : m_what(str) {}
00052 virtual char const* what() const throw();
00053 virtual ~bad_deref() throw();
00054 private:
00055 char const* m_what;
00056 };
00057
00058
00059
00060
00061
00062 template<typename T>
00063 struct allocator : ::std::allocator<T>
00064 {
00065 using std::allocator<T>::construct;
00066 typedef typename ::std::allocator<T>::pointer pointer;
00067
00068
00069 template<typename U>
00070 struct rebind
00071 {
00072
00073
00074 typedef allocator<U> other;
00075 };
00076
00077
00078 allocator() {}
00079
00080
00081 allocator(allocator const& x) : std::allocator<T>(x) {}
00082
00083
00084 template<typename U>
00085 allocator(allocator<U> const& x) : std::allocator<T>(x) {}
00086
00087
00088 void construct(pointer p) { new(p) T; }
00089
00090
00091 pointer copy(pointer p) { return new T(*p, *this); }
00092 };
00093
00094 #ifdef HAVE_BDWGC
00095
00096
00097
00098
00099 template<typename T>
00100 struct gc_allocator
00101 {
00102 typedef T* pointer;
00103 typedef T const* const_pointer;
00104 typedef T& reference;
00105 typedef T const& const_reference;
00106 typedef T value_type;
00107 typedef std::size_t size_type;
00108 typedef std::ptrdiff_t difference_type;
00109 template<typename U> struct rebind { typedef gc_allocator<U> other; };
00110
00111
00112 gc_allocator() {}
00113
00114 gc_allocator(gc_allocator const&) {}
00115
00116 template<typename U> gc_allocator(gc_allocator<U> const&) {}
00117
00118
00119 bool operator==(gc_allocator const&) { return true; }
00120
00121 bool operator!=(gc_allocator const&) { return false; }
00122
00123
00124 pointer address(reference x) const { return &x; }
00125
00126 const_pointer address(const_reference x) const { return &x; }
00127
00128
00129 pointer allocate(size_type n, const_pointer hint = 0)
00130 {
00131 return static_cast<pointer>(GC_malloc(n*sizeof(T)));
00132 }
00133
00134
00135 void deallocate(pointer p, size_type) {}
00136
00137
00138 size_type max_size()
00139 {
00140 return std::numeric_limits<size_type>::max();
00141 }
00142
00143
00144 void construct(pointer p, const_reference v) { ::new((void*)p) T(v); }
00145
00146
00147 void destroy(pointer p) {}
00148
00149
00150
00151 pointer copy(pointer p) { return p; }
00152 };
00153
00154
00155 namespace bits {
00156 struct weak_ptr_base
00157 {
00158 protected:
00159 explicit weak_ptr_base(void* ptr) throw();
00160
00161 void reset_base(void* ptr) throw();
00162
00163 static void* mt_get(void*) throw();
00164 static void* mt_eq(void*) throw();
00165 static void* mt_lt(void*) throw();
00166
00167 typedef void* atom_type[2];
00168 atom_type* m_atom;
00169 };
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 template <typename T>
00183 struct weak_ptr
00184 : private bits::weak_ptr_base
00185 {
00186 typedef T element_type;
00187
00188
00189
00190
00191 weak_ptr(T* ptr = 0) throw()
00192 : weak_ptr_base(ptr) {}
00193
00194 weak_ptr(weak_ptr const& wp) throw()
00195 : weak_ptr_base(wp) {}
00196
00197 weak_ptr& operator=(weak_ptr const& wp) throw()
00198 {
00199 m_atom = wp.m_atom;
00200 return *this;
00201 }
00202
00203
00204 T* get() const throw()
00205 {
00206 #ifdef MORE_CF_WITH_THREADS
00207 if (more::cf::there_are_other_treads())
00208 return static_cast<T*>(
00209 GC_call_with_alloc_lock(mt_get, (weak_ptr_base*)this));
00210 #endif
00211 return static_cast<T*>((*m_atom)[0]);
00212 }
00213
00214
00215 T& operator*() const throw(bad_deref, std::logic_error)
00216 {
00217 if (T* ptr = get())
00218 return *ptr;
00219 else if ((*m_atom)[1])
00220 throw bad_deref("more::gen::weak_ptr::operator->: "
00221 "Dereference of collected memory.");
00222 else
00223 throw std::logic_error("more::gen::weak_ptr::operator->: "
00224 "Dereference of null pointer.");
00225 }
00226
00227
00228 T* operator->() const throw(bad_deref, std::logic_error)
00229 {
00230 if (T* ptr = get())
00231 return *ptr;
00232 else if ((*m_atom)[1])
00233 throw bad_deref("more::gen::weak_ptr::operator->: "
00234 "Dereference of collected memory.");
00235 else
00236 throw std::logic_error("more::gen::weak_ptr::operator->: "
00237 "Dereference of null pointer.");
00238 }
00239
00240
00241
00242
00243 bool operator==(weak_ptr const& rhs) const throw()
00244 {
00245 #ifdef MORE_CF_WITH_THREADS
00246 if (more::cf::threre_are_other_threads()) {
00247 void* args[2] = { (weak_ptr_base*)this,
00248 (weak_ptr_base*)&rhs };
00249 return GC_call_with_alloc_lock(mt_eq, args);
00250 }
00251 #endif
00252 return (*m_atom)[1] == (*rhs.m_atom)[1];
00253 }
00254
00255
00256
00257
00258 bool operator<(weak_ptr const& rhs) const throw()
00259 {
00260 #ifdef MORE_CF_WITH_THREADS
00261 if (more::cf::threre_are_other_threads()) {
00262 void* args[2] = { (weak_ptr_base*)this,
00263 (weak_ptr_base*)&rhs };
00264 return GC_call_with_alloc_lock(mt_lt, args);
00265 }
00266 #endif
00267 return (*m_atom)[1] < (*rhs.m_atom)[1];
00268 }
00269
00270
00271 T* reset(T* p) throw() { reset_base(p); }
00272 };
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 template <typename T>
00283 struct hidden_ptr
00284 {
00285 typedef T element_type;
00286 private:
00287 typedef T* atom_type;
00288 public:
00289
00290
00291
00292
00293 hidden_ptr(T* ptr = 0) throw()
00294 : m_atom(GC_NEW_ATOMIC(atom_type)) { *m_atom = ptr; }
00295
00296 hidden_ptr(hidden_ptr const& wp) throw()
00297 : m_atom(wp.m_atom) {}
00298
00299 hidden_ptr& operator=(hidden_ptr const& wp) throw()
00300 {
00301 m_atom = wp.m_atom;
00302 return *this;
00303 }
00304
00305
00306
00307
00308
00309
00310 T* get() const throw() { return *m_atom; }
00311
00312
00313 T& operator*() const throw() { return *get(); }
00314
00315
00316 T* operator->() const throw() { return get(); }
00317
00318
00319 bool operator==(hidden_ptr const& rhs) const throw()
00320 {
00321 return *m_atom == *rhs.m_atom;
00322 }
00323
00324
00325 bool operator<(hidden_ptr const& rhs) const throw()
00326 {
00327 return *m_atom < *rhs.m_atom;
00328 }
00329
00330
00331 T* reset(T* ptr) throw()
00332 {
00333 m_atom = GC_NEW_ATOMIC(atom_type);
00334 *m_atom = ptr;
00335 }
00336
00337 private:
00338 atom_type* m_atom;
00339 };
00340
00341 #endif
00342
00343 }}
00344
00345 #endif