00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __OMNI_SMART_HPP_
00020 #define __OMNI_SMART_HPP_
00021
00022 #include <omni/defs.hpp>
00023
00024 #include <assert.h>
00025
00026 namespace omni
00027 {
00028 namespace smart
00029 {
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 class SharedObj: private omni::NonCopyable {
00053 protected:
00054 SharedObj();
00055 virtual ~SharedObj();
00056
00057 public:
00058 long N_refs() const;
00059
00060 public:
00061 void attach();
00062 bool detach();
00063
00064 private:
00065 long m_N_refs;
00066 };
00067
00068
00069 namespace details
00070 {
00071 template<typename T>
00072 class SharedPtr_Base;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 template<typename T>
00096 class SharedPtr: private details::SharedPtr_Base<T>::base_type {
00097 typedef typename details::SharedPtr_Base<T>::base_type inherited;
00098 typedef SharedPtr<T> ThisType;
00099
00100 public:
00101 typedef typename inherited::reference reference;
00102 typedef typename inherited::pointer pointer;
00103
00104 public:
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 SharedPtr()
00117 : inherited(0)
00118 {}
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 explicit SharedPtr(pointer ptr)
00129 : inherited(ptr)
00130 {
00131 attach();
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 SharedPtr(const ThisType &other)
00143 : inherited(other)
00144 {
00145 attach();
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155 ~SharedPtr()
00156 {
00157 detach();
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 ThisType& operator=(const ThisType &other)
00174 {
00175 ThisType t(other);
00176 swap(t);
00177
00178 return *this;
00179 }
00180
00181
00182 public:
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 reference operator*() const
00193 {
00194 const pointer ptr = get();
00195 return *ptr;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 pointer operator->() const
00207 {
00208 return get();
00209 }
00210
00211 public:
00212
00213
00214
00215
00216
00217
00218
00219
00220 pointer get() const
00221 {
00222 return inherited::get();
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 bool unique() const
00235 {
00236 return (get() != 0)
00237 && (N_refs() == 1);
00238 }
00239
00240 public:
00241
00242 typedef pointer (ThisType::*unspecified_bool_type)() const;
00243
00244
00245 operator unspecified_bool_type() const
00246 {
00247 return (get() == 0) ? 0 : &ThisType::get;
00248 }
00249
00250
00251 bool operator!() const
00252 {
00253 return get() == 0;
00254 }
00255
00256
00257 void swap(ThisType &other)
00258 {
00259 inherited::swap(other);
00260 }
00261 };
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276 template<typename T> inline
00277 bool operator==(const SharedPtr<T> &x, const SharedPtr<T> &y)
00278 {
00279 return x.get() == y.get();
00280 }
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 template<typename T> inline
00295 bool operator==(const SharedPtr<T> &x, const T *y)
00296 {
00297 return x.get() == y;
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 template<typename T> inline
00313 bool operator==(const T *x, const SharedPtr<T> &y)
00314 {
00315 return x == y.get();
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328 template<typename T> inline
00329 bool operator!=(const SharedPtr<T> &x, const SharedPtr<T> &y)
00330 {
00331 return x.get() != y.get();
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 template<typename T> inline
00345 bool operator!=(const SharedPtr<T> &x, const T *y)
00346 {
00347 return x.get() != y;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 template<typename T> inline
00361 bool operator!=(const T *x, const SharedPtr<T> &y)
00362 {
00363 return x != y.get();
00364 }
00365
00366
00367
00368
00369 template<typename T> inline
00370 void swap(SharedPtr<T> &x, SharedPtr<T> &y)
00371 {
00372 x.swap(y);
00373 }
00374
00375
00376 namespace details
00377 {
00378
00379
00380
00381 template<typename T>
00382 class SharedPtr_ThinBase: private omni::NonCopyable {
00383 typedef SharedPtr_ThinBase<T> ThisType;
00384
00385 protected:
00386 typedef T& reference;
00387 typedef T* pointer;
00388
00389 protected:
00390 explicit SharedPtr_ThinBase(pointer ptr)
00391 : m_ptr(ptr)
00392 {}
00393 SharedPtr_ThinBase(const ThisType &other)
00394 : m_ptr(other.m_ptr)
00395 {}
00396
00397 protected:
00398 pointer get() const
00399 {
00400 return m_ptr;
00401 }
00402 long N_refs() const
00403 {
00404 return m_ptr->SharedObj::N_refs();
00405 }
00406
00407 protected:
00408 void attach()
00409 {
00410 if (m_ptr)
00411 m_ptr->SharedObj::attach();
00412 }
00413 void detach()
00414 {
00415 if (m_ptr)
00416 m_ptr->SharedObj::detach();
00417 }
00418
00419 protected:
00420 void swap(ThisType &other)
00421 {
00422 pointer ptr = m_ptr;
00423 m_ptr = other.m_ptr;
00424 other.m_ptr = ptr;
00425 }
00426
00427 private:
00428 pointer m_ptr;
00429 };
00430
00431
00432
00433
00434 template<typename T>
00435 class SharedPtr_FatBase: private omni::NonCopyable {
00436 typedef SharedPtr_FatBase<T> ThisType;
00437
00438 protected:
00439 typedef T& reference;
00440 typedef T* pointer;
00441
00442 protected:
00443 explicit SharedPtr_FatBase(pointer ptr)
00444 : m_ptr(ptr), m_N(0)
00445 {}
00446 SharedPtr_FatBase(const ThisType &other)
00447 : m_ptr(other.m_ptr), m_N(other.m_N)
00448 {}
00449
00450 protected:
00451 pointer get() const
00452 {
00453 return m_ptr;
00454 }
00455 long N_refs() const
00456 {
00457 return m_N->N_refs();
00458 }
00459
00460 protected:
00461 void attach()
00462 {
00463 if (m_ptr && !m_N)
00464 m_N = new Counter();
00465
00466 if (m_N)
00467 m_N->attach();
00468 }
00469 void detach()
00470 {
00471 if (m_N)
00472 {
00473 if (m_N->detach())
00474 delete m_ptr;
00475 }
00476 }
00477
00478 protected:
00479
00480 void swap(ThisType &other)
00481 {
00482 pointer ptr = m_ptr;
00483 m_ptr = other.m_ptr;
00484 other.m_ptr = ptr;
00485
00486 Counter *n = m_N;
00487 m_N = other.m_N;
00488 other.m_N = n;
00489 }
00490
00491 private:
00492
00493 class Counter: public SharedObj {};
00494
00495 private:
00496 pointer m_ptr;
00497 Counter *m_N;
00498 };
00499
00500
00501 template<bool IsThin>
00502 struct SharedPtr_BaseSelector {
00503 template<typename T>
00504 struct Base {
00505 typedef SharedPtr_ThinBase<T> base_type;
00506 };
00507 };
00508
00509
00510 template<>
00511 struct SharedPtr_BaseSelector<false> {
00512 template<typename T>
00513 struct Base {
00514 typedef SharedPtr_FatBase<T> base_type;
00515 };
00516 };
00517
00518
00519
00520
00521
00522
00523 template<typename T>
00524 class SharedPtr_Base {
00525 private:
00526 struct YES { char dummy[666]; };
00527 struct NO { char dummy[999]; };
00528
00529 static YES check(const SharedObj*);
00530 static NO check(...);
00531
00532 enum { is_thin = sizeof(YES) == sizeof(check((const T*)0)) };
00533
00534 public:
00535 typedef typename SharedPtr_BaseSelector<is_thin>
00536 ::template Base<T>::base_type base_type;
00537 };
00538
00539 }
00540 }
00541 }
00542
00543 #endif // __OMNI_SMART_HPP_