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
00031 #ifndef PTLIB_SAFE_COLLECTION_H
00032 #define PTLIB_SAFE_COLLECTION_H
00033
00034 #ifdef P_USE_PRAGMA
00035 #pragma interface
00036 #endif
00037
00038
00119 class PSafeObject : public PObject
00120 {
00121 PCLASSINFO(PSafeObject, PObject);
00122 public:
00127 PSafeObject(
00128 PSafeObject * indirectLock = NULL
00129 );
00131
00152 PBoolean SafeReference();
00153
00164 PBoolean SafeDereference();
00165
00183 PBoolean LockReadOnly() const;
00184
00195 void UnlockReadOnly() const;
00196
00214 PBoolean LockReadWrite();
00215
00226 void UnlockReadWrite();
00227
00237 void SafeRemove();
00238
00246 PBoolean SafelyCanBeDeleted() const;
00247
00259 virtual bool GarbageCollection();
00261
00262 private:
00263 mutable PMutex safetyMutex;
00264 unsigned safeReferenceCount;
00265 bool safelyBeingRemoved;
00266 PReadWriteMutex safeInUseMutex;
00267 PReadWriteMutex * safeInUse;
00268
00269 friend class PSafeCollection;
00270 };
00271
00272
00275 class PSafeLockReadOnly
00276 {
00277 public:
00278 PSafeLockReadOnly(const PSafeObject & object);
00279 ~PSafeLockReadOnly();
00280 PBoolean Lock();
00281 void Unlock();
00282 PBoolean IsLocked() const { return locked; }
00283 bool operator!() const { return !locked; }
00284
00285 protected:
00286 PSafeObject & safeObject;
00287 PBoolean locked;
00288 };
00289
00290
00291
00294 class PSafeLockReadWrite
00295 {
00296 public:
00297 PSafeLockReadWrite(const PSafeObject & object);
00298 ~PSafeLockReadWrite();
00299 PBoolean Lock();
00300 void Unlock();
00301 PBoolean IsLocked() const { return locked; }
00302 bool operator!() const { return !locked; }
00303
00304 protected:
00305 PSafeObject & safeObject;
00306 PBoolean locked;
00307 };
00308
00309
00310
00323 class PSafeCollection : public PObject
00324 {
00325 PCLASSINFO(PSafeCollection, PObject);
00326 public:
00332 PSafeCollection(
00333 PCollection * collection
00334 );
00335
00339 ~PSafeCollection();
00341
00344 protected:
00353 virtual PBoolean SafeRemove(
00354 PSafeObject * obj
00355 );
00356
00365 virtual PBoolean SafeRemoveAt(
00366 PINDEX idx
00367 );
00368
00369 public:
00372 virtual void RemoveAll(
00373 PBoolean synchronous = false
00374 );
00375
00380 void AllowDeleteObjects(
00381 PBoolean yes = true
00382 ) { deleteObjects = yes; }
00383
00388 void DisallowDeleteObjects() { deleteObjects = false; }
00389
00394 virtual PBoolean DeleteObjectsToBeRemoved();
00395
00398 virtual void DeleteObject(PObject * object) const;
00399
00402 virtual void SetAutoDeleteObjects();
00403
00408 PINDEX GetSize() const;
00409
00414 PBoolean IsEmpty() const { return GetSize() == 0; }
00415
00418 const PMutex & GetMutex() const { return collectionMutex; }
00420
00421 protected:
00422 void CopySafeCollection(PCollection * other);
00423 void CopySafeDictionary(PAbstractDictionary * other);
00424 void SafeRemoveObject(PSafeObject * obj);
00425 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00426
00427 PCollection * collection;
00428 mutable PMutex collectionMutex;
00429 bool deleteObjects;
00430 PList<PSafeObject> toBeRemoved;
00431 PMutex removalMutex;
00432 PTimer deleteObjectsTimer;
00433
00434 private:
00435 PSafeCollection(const PSafeCollection & other) : PObject(other) { }
00436 void operator=(const PSafeCollection &) { }
00437
00438 friend class PSafePtrBase;
00439 };
00440
00441
00442 enum PSafetyMode {
00443 PSafeReference,
00444 PSafeReadOnly,
00445 PSafeReadWrite
00446 };
00447
00460 class PSafePtrBase : public PObject
00461 {
00462 PCLASSINFO(PSafePtrBase, PObject);
00463
00466 protected:
00474 PSafePtrBase(
00475 PSafeObject * obj = NULL,
00476 PSafetyMode mode = PSafeReference
00477 );
00478
00486 PSafePtrBase(
00487 const PSafeCollection & safeCollection,
00488 PSafetyMode mode,
00489 PINDEX idx
00490 );
00491
00499 PSafePtrBase(
00500 const PSafeCollection & safeCollection,
00501 PSafetyMode mode,
00502 PSafeObject * obj
00503 );
00504
00510 PSafePtrBase(
00511 const PSafePtrBase & enumerator
00512 );
00513
00514 public:
00517 ~PSafePtrBase();
00519
00526 virtual Comparison Compare(
00527 const PObject & obj
00528 ) const;
00529
00536 virtual void PrintOn(
00537 ostream &strm
00538 ) const;
00540
00545 virtual void SetNULL();
00546
00549 bool operator!() const { return currentObject == NULL; }
00550
00553 PSafetyMode GetSafetyMode() const { return lockMode; }
00554
00561 virtual PBoolean SetSafetyMode(
00562 PSafetyMode mode
00563 );
00564
00567 const PSafeCollection * GetCollection() const { return collection; }
00569
00570 virtual void Assign(const PSafePtrBase & ptr);
00571 virtual void Assign(const PSafeCollection & safeCollection);
00572 virtual void Assign(PSafeObject * obj);
00573 virtual void Assign(PINDEX idx);
00574
00575 protected:
00576 virtual void Next();
00577 virtual void Previous();
00578 virtual void DeleteObject(PSafeObject * obj);
00579
00580 enum EnterSafetyModeOption {
00581 WithReference,
00582 AlreadyReferenced
00583 };
00584 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00585
00586 enum ExitSafetyModeOption {
00587 WithDereference,
00588 NoDereference
00589 };
00590 void ExitSafetyMode(ExitSafetyModeOption ref);
00591
00592 virtual void LockPtr() { }
00593 virtual void UnlockPtr() { }
00594
00595 protected:
00596 const PSafeCollection * collection;
00597 PSafeObject * currentObject;
00598 PSafetyMode lockMode;
00599 };
00600
00601
00614 class PSafePtrMultiThreaded : public PSafePtrBase
00615 {
00616 PCLASSINFO(PSafePtrMultiThreaded, PSafePtrBase);
00617
00620 protected:
00628 PSafePtrMultiThreaded(
00629 PSafeObject * obj = NULL,
00630 PSafetyMode mode = PSafeReference
00631 );
00632
00640 PSafePtrMultiThreaded(
00641 const PSafeCollection & safeCollection,
00642 PSafetyMode mode,
00643 PINDEX idx
00644 );
00645
00653 PSafePtrMultiThreaded(
00654 const PSafeCollection & safeCollection,
00655 PSafetyMode mode,
00656 PSafeObject * obj
00657 );
00658
00664 PSafePtrMultiThreaded(
00665 const PSafePtrMultiThreaded & enumerator
00666 );
00667
00668 public:
00671 ~PSafePtrMultiThreaded();
00673
00680 virtual Comparison Compare(
00681 const PObject & obj
00682 ) const;
00684
00689 virtual void SetNULL();
00690
00697 virtual PBoolean SetSafetyMode(
00698 PSafetyMode mode
00699 );
00701
00702 virtual void Assign(const PSafePtrMultiThreaded & ptr);
00703 virtual void Assign(const PSafePtrBase & ptr);
00704 virtual void Assign(const PSafeCollection & safeCollection);
00705 virtual void Assign(PSafeObject * obj);
00706 virtual void Assign(PINDEX idx);
00707
00708 protected:
00709 virtual void Next();
00710 virtual void Previous();
00711 virtual void DeleteObject(PSafeObject * obj);
00712
00713 virtual void LockPtr() { m_mutex.Wait(); }
00714 virtual void UnlockPtr();
00715
00716 protected:
00717 mutable PMutex m_mutex;
00718 PSafeObject * m_objectToDelete;
00719 };
00720
00721
00742 template <class T, class BaseClass = PSafePtrBase> class PSafePtr : public BaseClass
00743 {
00744 public:
00754 PSafePtr(
00755 T * obj = NULL,
00756 PSafetyMode mode = PSafeReference
00757 ) : BaseClass(obj, mode) { }
00758
00766 PSafePtr(
00767 const PSafeCollection & safeCollection,
00768 PSafetyMode mode = PSafeReadWrite,
00769 PINDEX idx = 0
00770 ) : BaseClass(safeCollection, mode, idx) { }
00771
00779 PSafePtr(
00780 const PSafeCollection & safeCollection,
00781 PSafetyMode mode,
00782 PSafeObject * obj
00783 ) : BaseClass(safeCollection, mode, obj) { }
00784
00790 PSafePtr(
00791 const PSafePtr & ptr
00792 ) : BaseClass(ptr) { }
00793
00799 PSafePtr & operator=(const PSafePtr & ptr)
00800 {
00801 BaseClass::Assign(ptr);
00802 return *this;
00803 }
00804
00809 PSafePtr & operator=(const PSafeCollection & safeCollection)
00810 {
00811 BaseClass::Assign(safeCollection);
00812 return *this;
00813 }
00814
00830 PSafePtr & operator=(T * obj)
00831 {
00832 this->Assign(obj);
00833 return *this;
00834 }
00835
00845 PSafePtr & operator=(PINDEX idx)
00846 {
00847 BaseClass::Assign(idx);
00848 return *this;
00849 }
00850
00855 PSafePtr Set(T * obj)
00856 {
00857 this->LockPtr();
00858 PSafePtr oldPtr = *this;
00859 this->Assign(obj);
00860 this->UnlockPtr();
00861 return oldPtr;
00862 }
00864
00869 operator T*() const { return (T *)BaseClass::currentObject; }
00870
00873 T & operator*() const { return *(T *)PAssertNULL(BaseClass::currentObject); }
00874
00877 T * operator->() const { return (T *)PAssertNULL(BaseClass::currentObject); }
00878
00883 T * operator++(int)
00884 {
00885 T * previous = (T *)BaseClass::currentObject;
00886 BaseClass::Next();
00887 return previous;
00888 }
00889
00894 T * operator++()
00895 {
00896 BaseClass::Next();
00897 return (T *)BaseClass::currentObject;
00898 }
00899
00904 T * operator--(int)
00905 {
00906 T * previous = (T *)BaseClass::currentObject;
00907 BaseClass::Previous();
00908 return previous;
00909 }
00910
00915 T * operator--()
00916 {
00917 BaseClass::Previous();
00918 return (T *)BaseClass::currentObject;
00919 }
00921 };
00922
00923
00927 template <class Base, class Derived>
00928 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00929 {
00930
00931 PSafePtr<Derived> newPtr;
00932 Base * realPtr = oldPtr;
00933 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00934 newPtr.Assign(oldPtr);
00935 return newPtr;
00936 }
00937
00938
00949 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00950 {
00951 PCLASSINFO(PSafeColl, PSafeCollection);
00952 public:
00957 PSafeColl()
00958 : PSafeCollection(new Coll)
00959 { }
00960
00964 PSafeColl(const PSafeColl & other)
00965 : PSafeCollection(new Coll)
00966 {
00967 PWaitAndSignal lock2(other.collectionMutex);
00968 CopySafeCollection(dynamic_cast<Coll *>(other.collection));
00969 }
00970
00974 PSafeColl & operator=(const PSafeColl & other)
00975 {
00976 if (&other != this) {
00977 RemoveAll(true);
00978 PWaitAndSignal lock1(collectionMutex);
00979 PWaitAndSignal lock2(other.collectionMutex);
00980 CopySafeCollection(dynamic_cast<Coll *>(other.collection));
00981 }
00982 return *this;
00983 }
00985
00992 virtual PSafePtr<Base> Append(
00993 Base * obj,
00994 PSafetyMode mode = PSafeReference
00995 ) {
00996 PWaitAndSignal mutex(collectionMutex);
00997 if (PAssert(collection->GetObjectsIndex(obj) == P_MAX_INDEX, "Cannot insert safe object twice") &&
00998 obj->SafeReference())
00999 return PSafePtr<Base>(*this, mode, collection->Append(obj));
01000 return NULL;
01001 }
01002
01011 virtual PBoolean Remove(
01012 Base * obj
01013 ) {
01014 return SafeRemove(obj);
01015 }
01016
01025 virtual PBoolean RemoveAt(
01026 PINDEX idx
01027 ) {
01028 return SafeRemoveAt(idx);
01029 }
01030
01036 virtual PSafePtr<Base> GetAt(
01037 PINDEX idx,
01038 PSafetyMode mode = PSafeReadWrite
01039 ) {
01040 return PSafePtr<Base>(*this, mode, idx);
01041 }
01042
01048 virtual PSafePtr<Base> FindWithLock(
01049 const Base & value,
01050 PSafetyMode mode = PSafeReadWrite
01051 ) {
01052 collectionMutex.Wait();
01053 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
01054 collectionMutex.Signal();
01055 ptr.SetSafetyMode(mode);
01056 return ptr;
01057 }
01059 };
01060
01061
01066 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
01067 {
01068 public:
01069 typedef PSafePtr<Base> value_type;
01070 };
01071
01072
01077 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
01078 {
01079 public:
01080 typedef PSafePtr<Base> value_type;
01081 };
01082
01083
01088 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
01089 {
01090 public:
01091 typedef PSafePtr<Base> value_type;
01092 };
01093
01094
01105 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
01106 {
01107 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
01108 public:
01113 PSafeDictionaryBase()
01114 : PSafeCollection(new Coll) { }
01115
01119 PSafeDictionaryBase(const PSafeDictionaryBase & other)
01120 : PSafeCollection(new Coll)
01121 {
01122 PWaitAndSignal lock2(other.collectionMutex);
01123 CopySafeDictionary(dynamic_cast<Coll *>(other.collection));
01124 }
01125
01129 PSafeDictionaryBase & operator=(const PSafeDictionaryBase & other)
01130 {
01131 if (&other != this) {
01132 RemoveAll(true);
01133 PWaitAndSignal lock1(collectionMutex);
01134 PWaitAndSignal lock2(other.collectionMutex);
01135 CopySafeDictionary(dynamic_cast<Coll *>(other.collection));
01136 }
01137 return *this;
01138 }
01140
01147 virtual void SetAt(const Key & key, Base * obj)
01148 {
01149 collectionMutex.Wait();
01150 SafeRemove(((Coll *)collection)->GetAt(key));
01151 if (PAssert(collection->GetObjectsIndex(obj) == P_MAX_INDEX, "Cannot insert safe object twice") &&
01152 obj->SafeReference())
01153 ((Coll *)collection)->SetAt(key, obj);
01154 collectionMutex.Signal();
01155 }
01156
01165 virtual PBoolean RemoveAt(
01166 const Key & key
01167 ) {
01168 PWaitAndSignal mutex(collectionMutex);
01169 return SafeRemove(((Coll *)collection)->GetAt(key));
01170 }
01171
01174 virtual PBoolean Contains(
01175 const Key & key
01176 ) {
01177 PWaitAndSignal lock(collectionMutex);
01178 return ((Coll *)collection)->Contains(key);
01179 }
01180
01186 virtual PSafePtr<Base> GetAt(
01187 PINDEX idx,
01188 PSafetyMode mode = PSafeReadWrite
01189 ) {
01190 return PSafePtr<Base>(*this, mode, idx);
01191 }
01192
01198 virtual PSafePtr<Base> FindWithLock(
01199 const Key & key,
01200 PSafetyMode mode = PSafeReadWrite
01201 ) {
01202 collectionMutex.Wait();
01203 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01204 collectionMutex.Signal();
01205 ptr.SetSafetyMode(mode);
01206 return ptr;
01207 }
01208
01211 PArray<Key> GetKeys() const
01212 {
01213 PArray<Key> keys;
01214 collectionMutex.Wait();
01215 ((Coll *)collection)->AbstractGetKeys(keys);
01216 collectionMutex.Signal();
01217 return keys;
01218 }
01220 };
01221
01222
01227 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01228 {
01229 public:
01230 typedef PSafePtr<Base> value_type;
01231 };
01232
01233
01234 #endif // PTLIB_SAFE_COLLECTION_H
01235
01236
01237