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
00097 class PSafeObject : public PObject
00098 {
00099 PCLASSINFO(PSafeObject, PObject);
00100 public:
00105 PSafeObject(
00106 PSafeObject * indirectLock = NULL
00107 );
00109
00130 PBoolean SafeReference();
00131
00142 PBoolean SafeDereference();
00143
00161 PBoolean LockReadOnly() const;
00162
00173 void UnlockReadOnly() const;
00174
00192 PBoolean LockReadWrite();
00193
00204 void UnlockReadWrite();
00205
00215 void SafeRemove();
00216
00224 PBoolean SafelyCanBeDeleted() const;
00225
00237 virtual bool GarbageCollection();
00239
00240 private:
00241 mutable PMutex safetyMutex;
00242 unsigned safeReferenceCount;
00243 bool safelyBeingRemoved;
00244 PReadWriteMutex safeInUseMutex;
00245 PReadWriteMutex * safeInUse;
00246
00247 friend class PSafeCollection;
00248 };
00249
00250
00253 class PSafeLockReadOnly
00254 {
00255 public:
00256 PSafeLockReadOnly(const PSafeObject & object);
00257 ~PSafeLockReadOnly();
00258 PBoolean Lock();
00259 void Unlock();
00260 PBoolean IsLocked() const { return locked; }
00261 bool operator!() const { return !locked; }
00262
00263 protected:
00264 PSafeObject & safeObject;
00265 PBoolean locked;
00266 };
00267
00268
00269
00272 class PSafeLockReadWrite
00273 {
00274 public:
00275 PSafeLockReadWrite(const PSafeObject & object);
00276 ~PSafeLockReadWrite();
00277 PBoolean Lock();
00278 void Unlock();
00279 PBoolean IsLocked() const { return locked; }
00280 bool operator!() const { return !locked; }
00281
00282 protected:
00283 PSafeObject & safeObject;
00284 PBoolean locked;
00285 };
00286
00287
00288
00301 class PSafeCollection : public PObject
00302 {
00303 PCLASSINFO(PSafeCollection, PObject);
00304 public:
00310 PSafeCollection(
00311 PCollection * collection
00312 );
00313
00317 ~PSafeCollection();
00319
00322 protected:
00331 virtual PBoolean SafeRemove(
00332 PSafeObject * obj
00333 );
00334
00343 virtual PBoolean SafeRemoveAt(
00344 PINDEX idx
00345 );
00346
00347 public:
00350 virtual void RemoveAll(
00351 PBoolean synchronous = false
00352 );
00353
00358 void AllowDeleteObjects(
00359 PBoolean yes = true
00360 ) { deleteObjects = yes; }
00361
00366 void DisallowDeleteObjects() { deleteObjects = false; }
00367
00372 virtual PBoolean DeleteObjectsToBeRemoved();
00373
00376 virtual void DeleteObject(PObject * object) const;
00377
00380 virtual void SetAutoDeleteObjects();
00381
00386 PINDEX GetSize() const;
00387
00392 PBoolean IsEmpty() const { return GetSize() == 0; }
00393
00396 const PMutex & GetMutex() const { return collectionMutex; }
00398
00399 protected:
00400 void SafeRemoveObject(PSafeObject * obj);
00401 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00402
00403 PCollection * collection;
00404 mutable PMutex collectionMutex;
00405 PBoolean deleteObjects;
00406 PList<PSafeObject> toBeRemoved;
00407 PMutex removalMutex;
00408 PTimer deleteObjectsTimer;
00409
00410 friend class PSafePtrBase;
00411 };
00412
00413
00414 enum PSafetyMode {
00415 PSafeReference,
00416 PSafeReadOnly,
00417 PSafeReadWrite
00418 };
00419
00432 class PSafePtrBase : public PObject
00433 {
00434 PCLASSINFO(PSafePtrBase, PObject);
00435
00438 protected:
00446 PSafePtrBase(
00447 PSafeObject * obj = NULL,
00448 PSafetyMode mode = PSafeReference
00449 );
00450
00458 PSafePtrBase(
00459 const PSafeCollection & safeCollection,
00460 PSafetyMode mode,
00461 PINDEX idx
00462 );
00463
00471 PSafePtrBase(
00472 const PSafeCollection & safeCollection,
00473 PSafetyMode mode,
00474 PSafeObject * obj
00475 );
00476
00482 PSafePtrBase(
00483 const PSafePtrBase & enumerator
00484 );
00485
00486 public:
00489 ~PSafePtrBase();
00491
00498 virtual Comparison Compare(
00499 const PObject & obj
00500 ) const;
00502
00507 virtual void SetNULL();
00508
00511 bool operator!() const { return currentObject == NULL; }
00512
00515 PSafetyMode GetSafetyMode() const { return lockMode; }
00516
00523 virtual PBoolean SetSafetyMode(
00524 PSafetyMode mode
00525 );
00526
00529 const PSafeCollection * GetCollection() const { return collection; }
00531
00532 virtual void Assign(const PSafePtrBase & ptr);
00533 virtual void Assign(const PSafeCollection & safeCollection);
00534 virtual void Assign(PSafeObject * obj);
00535 virtual void Assign(PINDEX idx);
00536
00537 protected:
00538 virtual void Next();
00539 virtual void Previous();
00540 virtual void DeleteObject(PSafeObject * obj);
00541
00542 enum EnterSafetyModeOption {
00543 WithReference,
00544 AlreadyReferenced
00545 };
00546 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00547
00548 enum ExitSafetyModeOption {
00549 WithDereference,
00550 NoDereference
00551 };
00552 void ExitSafetyMode(ExitSafetyModeOption ref);
00553
00554 protected:
00555 const PSafeCollection * collection;
00556 PSafeObject * currentObject;
00557 PSafetyMode lockMode;
00558 };
00559
00560
00573 class PSafePtrMultiThreaded : public PSafePtrBase
00574 {
00575 PCLASSINFO(PSafePtrMultiThreaded, PSafePtrBase);
00576
00579 protected:
00587 PSafePtrMultiThreaded(
00588 PSafeObject * obj = NULL,
00589 PSafetyMode mode = PSafeReference
00590 );
00591
00599 PSafePtrMultiThreaded(
00600 const PSafeCollection & safeCollection,
00601 PSafetyMode mode,
00602 PINDEX idx
00603 );
00604
00612 PSafePtrMultiThreaded(
00613 const PSafeCollection & safeCollection,
00614 PSafetyMode mode,
00615 PSafeObject * obj
00616 );
00617
00623 PSafePtrMultiThreaded(
00624 const PSafePtrMultiThreaded & enumerator
00625 );
00626
00627 public:
00630 ~PSafePtrMultiThreaded();
00632
00639 virtual Comparison Compare(
00640 const PObject & obj
00641 ) const;
00643
00648 virtual void SetNULL();
00649
00656 virtual PBoolean SetSafetyMode(
00657 PSafetyMode mode
00658 );
00660
00661 virtual void Assign(const PSafePtrMultiThreaded & ptr);
00662 virtual void Assign(const PSafePtrBase & ptr);
00663 virtual void Assign(const PSafeCollection & safeCollection);
00664 virtual void Assign(PSafeObject * obj);
00665 virtual void Assign(PINDEX idx);
00666
00667 protected:
00668 virtual void Next();
00669 virtual void Previous();
00670 virtual void DeleteObject(PSafeObject * obj);
00671
00672 void Lock() { m_mutex.Wait(); }
00673 void Unlock();
00674
00675 protected:
00676 mutable PMutex m_mutex;
00677 PSafeObject * m_objectToDelete;
00678 };
00679
00680
00701 template <class T, class BaseClass = PSafePtrBase> class PSafePtr : public BaseClass
00702 {
00703 public:
00713 PSafePtr(
00714 T * obj = NULL,
00715 PSafetyMode mode = PSafeReference
00716 ) : BaseClass(obj, mode) { }
00717
00725 PSafePtr(
00726 const PSafeCollection & safeCollection,
00727 PSafetyMode mode = PSafeReadWrite,
00728 PINDEX idx = 0
00729 ) : BaseClass(safeCollection, mode, idx) { }
00730
00738 PSafePtr(
00739 const PSafeCollection & safeCollection,
00740 PSafetyMode mode,
00741 PSafeObject * obj
00742 ) : BaseClass(safeCollection, mode, obj) { }
00743
00749 PSafePtr(
00750 const PSafePtr & ptr
00751 ) : BaseClass(ptr) { }
00752
00758 PSafePtr & operator=(const PSafePtr & ptr)
00759 {
00760 BaseClass::Assign(ptr);
00761 return *this;
00762 }
00763
00768 PSafePtr & operator=(const PSafeCollection & safeCollection)
00769 {
00770 BaseClass::Assign(safeCollection);
00771 return *this;
00772 }
00773
00789 PSafePtr & operator=(T * obj)
00790 {
00791 Assign(obj);
00792 return *this;
00793 }
00794
00804 PSafePtr & operator=(PINDEX idx)
00805 {
00806 BaseClass::Assign(idx);
00807 return *this;
00808 }
00810
00815 operator T*() const { return (T *)BaseClass::currentObject; }
00816
00819 T & operator*() const { return *(T *)PAssertNULL(BaseClass::currentObject); }
00820
00823 T * operator->() const { return (T *)PAssertNULL(BaseClass::currentObject); }
00824
00829 T * operator++(int)
00830 {
00831 T * previous = (T *)BaseClass::currentObject;
00832 BaseClass::Next();
00833 return previous;
00834 }
00835
00840 T * operator++()
00841 {
00842 BaseClass::Next();
00843 return (T *)BaseClass::currentObject;
00844 }
00845
00850 T * operator--(int)
00851 {
00852 T * previous = (T *)BaseClass::currentObject;
00853 BaseClass::Previous();
00854 return previous;
00855 }
00856
00861 T * operator--()
00862 {
00863 BaseClass::Previous();
00864 return (T *)BaseClass::currentObject;
00865 }
00867
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 };
00883
00884
00888 template <class Base, class Derived>
00889 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00890 {
00891
00892 PSafePtr<Derived> newPtr;
00893 Base * realPtr = oldPtr;
00894 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00895 newPtr.Assign(oldPtr);
00896 return newPtr;
00897 }
00898
00899
00910 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00911 {
00912 PCLASSINFO(PSafeColl, PSafeCollection);
00913 public:
00918 PSafeColl()
00919 : PSafeCollection(new Coll)
00920 { }
00922
00929 virtual PSafePtr<Base> Append(
00930 Base * obj,
00931 PSafetyMode mode = PSafeReference
00932 ) {
00933 PWaitAndSignal mutex(collectionMutex);
00934 if (PAssert(collection->GetObjectsIndex(obj) == P_MAX_INDEX, "Cannot insert safe object twice") &&
00935 obj->SafeReference())
00936 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00937 return NULL;
00938 }
00939
00948 virtual PBoolean Remove(
00949 Base * obj
00950 ) {
00951 return SafeRemove(obj);
00952 }
00953
00962 virtual PBoolean RemoveAt(
00963 PINDEX idx
00964 ) {
00965 return SafeRemoveAt(idx);
00966 }
00967
00973 virtual PSafePtr<Base> GetAt(
00974 PINDEX idx,
00975 PSafetyMode mode = PSafeReadWrite
00976 ) {
00977 return PSafePtr<Base>(*this, mode, idx);
00978 }
00979
00985 virtual PSafePtr<Base> FindWithLock(
00986 const Base & value,
00987 PSafetyMode mode = PSafeReadWrite
00988 ) {
00989 collectionMutex.Wait();
00990 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00991 collectionMutex.Signal();
00992 ptr.SetSafetyMode(mode);
00993 return ptr;
00994 }
00996 };
00997
00998
01003 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
01004 {
01005 public:
01006 typedef PSafePtr<Base> value_type;
01007 };
01008
01009
01014 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
01015 {
01016 public:
01017 typedef PSafePtr<Base> value_type;
01018 };
01019
01020
01025 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
01026 {
01027 public:
01028 typedef PSafePtr<Base> value_type;
01029 };
01030
01031
01042 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
01043 {
01044 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
01045 public:
01050 PSafeDictionaryBase()
01051 : PSafeCollection(new Coll) { }
01053
01060 virtual void SetAt(const Key & key, Base * obj)
01061 {
01062 collectionMutex.Wait();
01063 SafeRemove(((Coll *)collection)->GetAt(key));
01064 if (PAssert(collection->GetObjectsIndex(obj) == P_MAX_INDEX, "Cannot insert safe object twice") &&
01065 obj->SafeReference())
01066 ((Coll *)collection)->SetAt(key, obj);
01067 collectionMutex.Signal();
01068 }
01069
01078 virtual PBoolean RemoveAt(
01079 const Key & key
01080 ) {
01081 PWaitAndSignal mutex(collectionMutex);
01082 return SafeRemove(((Coll *)collection)->GetAt(key));
01083 }
01084
01087 virtual PBoolean Contains(
01088 const Key & key
01089 ) {
01090 PWaitAndSignal lock(collectionMutex);
01091 return ((Coll *)collection)->Contains(key);
01092 }
01093
01099 virtual PSafePtr<Base> GetAt(
01100 PINDEX idx,
01101 PSafetyMode mode = PSafeReadWrite
01102 ) {
01103 return PSafePtr<Base>(*this, mode, idx);
01104 }
01105
01111 virtual PSafePtr<Base> FindWithLock(
01112 const Key & key,
01113 PSafetyMode mode = PSafeReadWrite
01114 ) {
01115 collectionMutex.Wait();
01116 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01117 collectionMutex.Signal();
01118 ptr.SetSafetyMode(mode);
01119 return ptr;
01120 }
01122 };
01123
01124
01129 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01130 {
01131 public:
01132 typedef PSafePtr<Base> value_type;
01133 };
01134
01135
01136 #endif // PTLIB_SAFE_COLLECTION_H
01137
01138
01139