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
00031
00032
00033 #pragma once
00034
00035
00036 #include "../api_core.h"
00037 #include "system.h"
00038 #include "mutex.h"
00039 #include "exception.h"
00040 #include "memory_pool.h"
00041
00042 #ifndef WIN32
00043 #include <cstring>
00044 #endif
00045
00048 class CL_API_CORE CL_SharedPtr_Impl
00049 {
00050 public:
00051 virtual ~CL_SharedPtr_Impl() { return; }
00052 };
00053
00056 template <typename Type>
00057 class CL_SharedPtr_Deleter
00058 {
00059 public:
00060 CL_SharedPtr_Deleter(Type *instance) : instance(instance) { return; }
00061
00062 virtual ~CL_SharedPtr_Deleter() { delete instance; }
00063
00064 Type *instance;
00065 };
00066
00069 template <typename Type>
00070 class CL_SharedPtr_DeleterPool
00071 {
00072 public:
00073 CL_SharedPtr_DeleterPool(Type *instance, CL_MemoryPool *pool)
00074 : instance(instance), pool(pool) { return; }
00075
00076 virtual ~CL_SharedPtr_DeleterPool() { instance->~Type(); operator delete(instance, pool); }
00077
00078 Type *instance;
00079
00080 CL_MemoryPool *pool;
00081 };
00082
00085 template <typename Type>
00086 class CL_SharedPtr_DeleterCallback
00087 {
00088 public:
00089 CL_SharedPtr_DeleterCallback(Type *instance, void (*free_callback)(Type *))
00090 : instance(instance), free_callback(free_callback) { return; }
00091
00092 virtual ~CL_SharedPtr_DeleterCallback() { free_callback(instance); }
00093
00094 Type *instance;
00095
00096 void (*free_callback)(Type *);
00097 };
00098
00101 template <typename Type, typename FreeClass>
00102 class CL_SharedPtr_DeleterClassCallback
00103 {
00104 public:
00105 CL_SharedPtr_DeleterClassCallback(Type *instance, FreeClass *free_class, void (FreeClass::*free_callback)(Type *))
00106 : instance(instance), free_class(free_class), free_callback(free_callback) { return; }
00107
00108 virtual ~CL_SharedPtr_DeleterClassCallback() { (free_class->*free_callback)(instance); }
00109
00110 Type *instance;
00111
00112 FreeClass *free_class;
00113
00114 void (FreeClass::*free_callback)(Type *);
00115 };
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 #define CL_DELETER_SIZE (sizeof(CL_SharedPtr_DeleterClassCallback<int,CL_MemoryPool>))
00134
00137 class CL_API_CORE CL_SharedPtr_Link
00138 {
00139 public:
00140 CL_SharedPtr_Link()
00141 : mutex(0), prev(0), next(0), weak_link(0)
00142 {
00143 }
00144
00145 CL_SharedPtr_Link(const CL_SharedPtr_Link ©)
00146 : mutex(0), prev(0), next(0), weak_link(0)
00147 {
00148 connect(copy);
00149 }
00150
00151 ~CL_SharedPtr_Link()
00152 {
00153 if (prev != 0 || next != 0)
00154 disconnect();
00155
00156
00157
00158
00159
00160
00161
00162 }
00163
00164 CL_SharedPtr_Link &operator =(const CL_SharedPtr_Link ©)
00165 {
00166 if (this != ©)
00167 {
00168 disconnect();
00169 connect(copy);
00170 }
00171 return *this;
00172 }
00173
00174 template <typename Type>
00175 void create_deleter(Type *instance)
00176 {
00177 #ifdef DEBUG_SHAREDPTR
00178 if (sizeof(CL_SharedPtr_Deleter<Type>) > CL_DELETER_SIZE)
00179 throw CL_Exception("CL_DELETER_SIZE buffer too small!");
00180 #endif
00181 CL_SharedPtr_Deleter<Type> *d = (CL_SharedPtr_Deleter<Type> *) deleter;
00182 CL_System::call_constructor(d, instance);
00183 }
00184
00185 template <typename Type>
00186 void create_deleter(Type *ptr, CL_MemoryPool *pool)
00187 {
00188 #ifdef DEBUG_SHAREDPTR
00189 if (sizeof(CL_SharedPtr_DeleterPool<Type>) > CL_DELETER_SIZE)
00190 throw CL_Exception("CL_DELETER_SIZE buffer too small!");
00191 #endif
00192 CL_SharedPtr_DeleterPool<Type> *d = (CL_SharedPtr_DeleterPool<Type> *) deleter;
00193 CL_System::call_constructor(d, ptr, pool);
00194 }
00195
00196 template <typename Type>
00197 void create_deleter(Type *ptr, void (*free_callback)(Type *ptr))
00198 {
00199 #ifdef DEBUG_SHAREDPTR
00200 if (sizeof(CL_SharedPtr_DeleterCallback<Type>) > CL_DELETER_SIZE)
00201 throw CL_Exception("CL_DELETER_SIZE buffer too small!");
00202 #endif
00203 CL_SharedPtr_DeleterCallback<Type> *d = (CL_SharedPtr_DeleterCallback<Type> *) deleter;
00204 CL_System::call_constructor(d, ptr, free_callback);
00205 }
00206
00207 template <typename Type, typename FreeClass>
00208 void create_deleter(Type *ptr, FreeClass *free_class, void (FreeClass::*free_callback)(Type *ptr))
00209 {
00210 #ifdef DEBUG_SHAREDPTR
00211 if (sizeof(CL_SharedPtr_DeleterClassCallback<Type, FreeClass>) > CL_DELETER_SIZE)
00212 throw CL_Exception("CL_DELETER_SIZE buffer too small!");
00213 #endif
00214 CL_SharedPtr_DeleterClassCallback<Type, FreeClass> *d = (CL_SharedPtr_DeleterClassCallback<Type, FreeClass> *) deleter;
00215 CL_System::call_constructor(d, ptr, free_class, free_callback);
00216 }
00217
00218 void call_deleter()
00219 {
00220 CL_SharedPtr_Impl *d = (CL_SharedPtr_Impl *) deleter;
00221 CL_System::call_destructor(d);
00222 }
00223
00224 void connect(const CL_SharedPtr_Link ©)
00225 {
00226 CL_MutexSection mutex_lock(copy.mutex);
00227 #ifdef DEBUG_SHAREDPTR
00228 if (prev != 0 || next != 0)
00229 throw CL_Exception("Memory corruption error in CL_SharedPtr_Link");
00230 assert_list(©);
00231 #endif
00232 mutex = copy.mutex;
00233 next = copy.next;
00234 prev = (CL_SharedPtr_Link *) ©
00235 copy.next = this;
00236 if (next)
00237 next->prev = this;
00238 memcpy(deleter, copy.deleter, CL_DELETER_SIZE);
00239 #ifdef DEBUG_SHAREDPTR
00240 assert_list(prev);
00241 #endif
00242 }
00243
00245
00246 bool disconnect()
00247 {
00248 CL_MutexSection mutex_lock(mutex);
00249 #ifdef DEBUG_SHAREDPTR
00250 assert_list(prev);
00251 #endif
00252 if (weak_link == 2)
00253 weak_link = 1;
00254 if (prev == 0 && next == 0)
00255 return true;
00256
00257 if (prev)
00258 prev->next = next;
00259 if (next)
00260 next->prev = prev;
00261 #ifdef DEBUG_SHAREDPTR
00262 assert_list(prev);
00263 #endif
00264
00265 CL_SharedPtr_Link *cur = prev;
00266 while (cur)
00267 {
00268 if (!cur->weak_link)
00269 {
00270 prev = 0;
00271 next = 0;
00272 return false;
00273 }
00274 cur = cur->prev;
00275 }
00276
00277 cur = next;
00278 while (cur)
00279 {
00280 if (!cur->weak_link)
00281 {
00282 prev = 0;
00283 next = 0;
00284 return false;
00285 }
00286 cur = cur->next;
00287 }
00288
00289
00290
00291
00292 cur = prev;
00293 while (cur)
00294 {
00295 cur->weak_link = 2;
00296 cur = cur->prev;
00297 }
00298
00299 cur = next;
00300 while (cur)
00301 {
00302 cur->weak_link = 2;
00303 cur = cur->next;
00304 }
00305
00306 prev = 0;
00307 next = 0;
00308 return true;
00309 }
00310
00311 void set_weak_link() { weak_link = 1; }
00312
00313 bool is_invalid_weak_link() const { return weak_link != 1; }
00314
00315 #ifdef DEBUG_SHAREDPTR
00316 void assert_list(const CL_SharedPtr_Link *ptr)
00317 {
00318 if (ptr == 0)
00319 return;
00320 while (ptr->prev != 0)
00321 {
00322 if (ptr->prev->next != ptr)
00323 throw CL_Exception("Memory corruption error in CL_SharedPtr_Link");
00324 ptr = ptr->prev;
00325 }
00326 while (ptr && ptr->next)
00327 {
00328 if (ptr->next->prev != ptr)
00329 throw CL_Exception("Memory corruption error in CL_SharedPtr_Link");
00330 ptr = ptr->next;
00331 }
00332 }
00333 #endif
00334
00335 public:
00336 mutable CL_Mutex *mutex;
00337
00338 private:
00339 mutable CL_SharedPtr_Link *prev;
00340
00341 mutable CL_SharedPtr_Link *next;
00342
00343 char deleter[CL_DELETER_SIZE];
00344
00345 unsigned char weak_link;
00346 };
00347
00351 class CL_API_CORE CL_UnknownSharedPtr : public CL_SharedPtr_Link
00352 {
00353 public:
00354 CL_UnknownSharedPtr()
00355 : ptr(0)
00356 {
00357 }
00358
00359 CL_UnknownSharedPtr(const CL_SharedPtr_Link &link, void *ptr)
00360 : ptr(ptr)
00361 {
00362 connect(link);
00363 }
00364
00365 CL_UnknownSharedPtr(const CL_UnknownSharedPtr ©)
00366 : ptr(0)
00367 {
00368 connect(copy);
00369 ptr = copy.ptr;
00370 }
00371
00372 ~CL_UnknownSharedPtr()
00373 {
00374 disconnect();
00375 }
00376
00377 CL_UnknownSharedPtr &operator =(const CL_UnknownSharedPtr ©)
00378 {
00379 if (this == ©)
00380 return *this;
00381 disconnect();
00382 connect(copy);
00383 ptr = copy.ptr;
00384 return *this;
00385 }
00386
00388
00390 bool disconnect()
00391 {
00392 bool result = CL_SharedPtr_Link::disconnect();
00393 if ( result && ptr )
00394 {
00395 call_deleter();
00396 }
00397 ptr = NULL;
00398 return result;
00399 }
00400
00402
00403 bool is_null() const { return ptr == 0; }
00404
00406
00407 void *get() { return ptr; }
00408
00410
00411 const void *get() const { return ptr; }
00412
00413 operator void *() { return ptr; }
00414
00415 operator const void *() const { return ptr; }
00416
00417 void *operator ->() { return ptr; }
00418
00419 const void *operator ->() const { return ptr; }
00420
00421 template <typename OtherType>
00422 bool operator ==(OtherType *other) const { return ptr == other; }
00423
00424 template <typename OtherType>
00425 bool operator !=(OtherType *other) const { return ptr != other; }
00426
00427 template <typename OtherType>
00428 bool operator <(OtherType *other) const { return ptr < other; }
00429
00430 template <typename OtherType>
00431 bool operator <=(OtherType *other) const { return ptr <= other; }
00432
00433 template <typename OtherType>
00434 bool operator >(OtherType *other) const { return ptr > other; }
00435
00436 template <typename OtherType>
00437 bool operator >=(OtherType *other) const { return ptr >= other; }
00438
00439 public:
00440 void *ptr;
00441 };
00442
00446 template <typename Type>
00447 class CL_SharedPtr : public CL_SharedPtr_Link
00448 {
00449 public:
00450 CL_SharedPtr()
00451 : ptr(0)
00452 {
00453 }
00454
00455 CL_SharedPtr(const CL_SharedPtr<Type> ©)
00456 : ptr(0)
00457 {
00458 connect(copy);
00459 ptr = copy.ptr;
00460 }
00461
00462 explicit CL_SharedPtr(const CL_UnknownSharedPtr ©)
00463 : ptr(0)
00464 {
00465 connect(copy);
00466 ptr = (Type *) copy.ptr;
00467 }
00468
00469 template <typename InitType>
00470 explicit CL_SharedPtr(InitType *ptr)
00471 : ptr(ptr)
00472 {
00473 mutex = CL_System::get_sharedptr_mutex();
00474 if (ptr)
00475 create_deleter(ptr);
00476 }
00477
00478 template <typename InitType>
00479 explicit CL_SharedPtr(InitType *ptr, CL_Mutex *ref_mutex)
00480 : ptr(ptr)
00481 {
00482 mutex = ref_mutex;
00483 if (ptr)
00484 create_deleter(ptr);
00485 }
00486
00487 template <typename InitType>
00488 explicit CL_SharedPtr(InitType *ptr, CL_MemoryPool *memory_pool)
00489 : ptr(ptr)
00490 {
00491 mutex = CL_System::get_sharedptr_mutex();
00492 if (ptr)
00493 create_deleter(ptr, memory_pool);
00494 }
00495
00496 template <typename InitType>
00497 explicit CL_SharedPtr(InitType *ptr, CL_MemoryPool *memory_pool, CL_Mutex *ref_mutex)
00498 : ptr(ptr)
00499 {
00500 mutex = ref_mutex;
00501 if (ptr)
00502 create_deleter(ptr, memory_pool);
00503 }
00504
00505 template <typename InitType>
00506 explicit CL_SharedPtr(InitType *ptr, void (*free_callback)(InitType *ptr))
00507 : ptr(ptr)
00508 {
00509 mutex = CL_System::get_sharedptr_mutex();
00510 if (ptr)
00511 create_deleter(ptr, free_callback);
00512 }
00513
00514 template <typename InitType>
00515 explicit CL_SharedPtr(InitType *ptr, void (*free_callback)(InitType *ptr), CL_Mutex *ref_mutex)
00516 : ptr(ptr)
00517 {
00518 mutex = ref_mutex;
00519 if (ptr)
00520 create_deleter(ptr, free_callback);
00521 }
00522
00523 template <typename InitType, typename FreeClass>
00524 explicit CL_SharedPtr(InitType *ptr, FreeClass *free_class, void (FreeClass::*free_callback)(InitType *ptr))
00525 : ptr(ptr)
00526 {
00527 mutex = CL_System::get_sharedptr_mutex();
00528 if (ptr)
00529 create_deleter(ptr, free_class, free_callback);
00530 }
00531
00532 template <typename InitType, typename FreeClass>
00533 explicit CL_SharedPtr(InitType *ptr, FreeClass *free_class, void (FreeClass::*free_callback)(InitType *ptr), CL_Mutex *ref_mutex)
00534 : ptr(ptr)
00535 {
00536 mutex = ref_mutex;
00537 if (ptr)
00538 create_deleter(ptr, free_class, free_callback);
00539 }
00540
00541 CL_SharedPtr(const CL_SharedPtr_Link &link, Type *ptr)
00542 : ptr(ptr)
00543 {
00544 connect(link);
00545 }
00546
00547 ~CL_SharedPtr()
00548 {
00549 disconnect();
00550 }
00551
00552 CL_SharedPtr &operator =(const CL_SharedPtr ©)
00553 {
00554 if (this == ©)
00555 return *this;
00556 disconnect();
00557 connect(copy);
00558 ptr = copy.ptr;
00559 return *this;
00560 }
00561
00563
00565 bool disconnect()
00566 {
00567 bool result = CL_SharedPtr_Link::disconnect();
00568 if ( result && ptr )
00569 {
00570 call_deleter();
00571 }
00572 ptr = NULL;
00573 return result;
00574 }
00575
00577
00578 bool is_null() const { return ptr == 0; }
00579
00581
00582 Type *get() { return ptr; }
00583
00585
00586 const Type *get() const { return ptr; }
00587
00588 operator Type *() { return ptr; }
00589
00590 operator const Type *() const { return ptr; }
00591
00592 operator CL_UnknownSharedPtr() { return CL_UnknownSharedPtr(*this, ptr); }
00593
00594 operator CL_UnknownSharedPtr() const { return CL_UnknownSharedPtr(*this, (Type *) ptr); }
00595
00596 Type *operator ->() { return ptr; }
00597
00598 const Type *operator ->() const { return ptr; }
00599
00600 template <typename OtherType>
00601 bool operator ==(OtherType *other) const { return ptr == other; }
00602
00603 template <typename OtherType>
00604 bool operator !=(OtherType *other) const { return ptr != other; }
00605
00606 template <typename OtherType>
00607 bool operator <(OtherType *other) const { return ptr < other; }
00608
00609 template <typename OtherType>
00610 bool operator <=(OtherType *other) const { return ptr <= other; }
00611
00612 template <typename OtherType>
00613 bool operator >(OtherType *other) const { return ptr > other; }
00614
00615 template <typename OtherType>
00616 bool operator >=(OtherType *other) const { return ptr >= other; }
00617
00618 public:
00619 Type *ptr;
00620
00621 };
00622
00623
00624