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 = PFalse
00352 );
00353
00358 void AllowDeleteObjects(
00359 PBoolean yes = PTrue
00360 ) { deleteObjects = yes; }
00361
00366 void DisallowDeleteObjects() { deleteObjects = PFalse; }
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
00541 enum EnterSafetyModeOption {
00542 WithReference,
00543 AlreadyReferenced
00544 };
00545 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00546
00547 enum ExitSafetyModeOption {
00548 WithDereference,
00549 NoDereference
00550 };
00551 void ExitSafetyMode(ExitSafetyModeOption ref);
00552
00553 protected:
00554 const PSafeCollection * collection;
00555 PSafeObject * currentObject;
00556 PSafetyMode lockMode;
00557 };
00558
00559
00572 class PSafePtrMultiThreaded : public PSafePtrBase
00573 {
00574 PCLASSINFO(PSafePtrMultiThreaded, PSafePtrBase);
00575
00578 protected:
00586 PSafePtrMultiThreaded(
00587 PSafeObject * obj = NULL,
00588 PSafetyMode mode = PSafeReference
00589 );
00590
00598 PSafePtrMultiThreaded(
00599 const PSafeCollection & safeCollection,
00600 PSafetyMode mode,
00601 PINDEX idx
00602 );
00603
00611 PSafePtrMultiThreaded(
00612 const PSafeCollection & safeCollection,
00613 PSafetyMode mode,
00614 PSafeObject * obj
00615 );
00616
00622 PSafePtrMultiThreaded(
00623 const PSafePtrMultiThreaded & enumerator
00624 );
00625
00626 public:
00629 ~PSafePtrMultiThreaded();
00631
00638 virtual Comparison Compare(
00639 const PObject & obj
00640 ) const;
00642
00647 virtual void SetNULL();
00648
00655 virtual PBoolean SetSafetyMode(
00656 PSafetyMode mode
00657 );
00659
00660 virtual void Assign(const PSafePtrMultiThreaded & ptr);
00661 virtual void Assign(const PSafePtrBase & ptr);
00662 virtual void Assign(const PSafeCollection & safeCollection);
00663 virtual void Assign(PSafeObject * obj);
00664 virtual void Assign(PINDEX idx);
00665
00666 protected:
00667 virtual void Next();
00668 virtual void Previous();
00669
00670 protected:
00671 mutable PMutex m_mutex;
00672 };
00673
00674
00695 template <class T, class BaseClass = PSafePtrBase> class PSafePtr : public BaseClass
00696 {
00697 public:
00707 PSafePtr(
00708 T * obj = NULL,
00709 PSafetyMode mode = PSafeReference
00710 ) : BaseClass(obj, mode) { }
00711
00719 PSafePtr(
00720 const PSafeCollection & safeCollection,
00721 PSafetyMode mode = PSafeReadWrite,
00722 PINDEX idx = 0
00723 ) : BaseClass(safeCollection, mode, idx) { }
00724
00732 PSafePtr(
00733 const PSafeCollection & safeCollection,
00734 PSafetyMode mode,
00735 PSafeObject * obj
00736 ) : BaseClass(safeCollection, mode, obj) { }
00737
00743 PSafePtr(
00744 const PSafePtr & ptr
00745 ) : BaseClass(ptr) { }
00746
00752 PSafePtr & operator=(const PSafePtr & ptr)
00753 {
00754 BaseClass::Assign(ptr);
00755 return *this;
00756 }
00757
00762 PSafePtr & operator=(const PSafeCollection & safeCollection)
00763 {
00764 BaseClass::Assign(safeCollection);
00765 return *this;
00766 }
00767
00783 PSafePtr & operator=(T * obj)
00784 {
00785 Assign(obj);
00786 return *this;
00787 }
00788
00798 PSafePtr & operator=(PINDEX idx)
00799 {
00800 BaseClass::Assign(idx);
00801 return *this;
00802 }
00804
00809 operator T*() const { return (T *)BaseClass::currentObject; }
00810
00813 T & operator*() const { return *(T *)PAssertNULL(BaseClass::currentObject); }
00814
00817 T * operator->() const { return (T *)PAssertNULL(BaseClass::currentObject); }
00818
00823 T * operator++(int)
00824 {
00825 T * previous = (T *)BaseClass::currentObject;
00826 BaseClass::Next();
00827 return previous;
00828 }
00829
00834 T * operator++()
00835 {
00836 BaseClass::Next();
00837 return (T *)BaseClass::currentObject;
00838 }
00839
00844 T * operator--(int)
00845 {
00846 T * previous = (T *)BaseClass::currentObject;
00847 BaseClass::Previous();
00848 return previous;
00849 }
00850
00855 T * operator--()
00856 {
00857 BaseClass::Previous();
00858 return (T *)BaseClass::currentObject;
00859 }
00861
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 };
00877
00878
00882 template <class Base, class Derived>
00883 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00884 {
00885
00886 PSafePtr<Derived> newPtr;
00887 Base * realPtr = oldPtr;
00888 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00889 newPtr.Assign(oldPtr);
00890 return newPtr;
00891 }
00892
00893
00904 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00905 {
00906 PCLASSINFO(PSafeColl, PSafeCollection);
00907 public:
00912 PSafeColl()
00913 : PSafeCollection(new Coll)
00914 { }
00916
00923 virtual PSafePtr<Base> Append(
00924 Base * obj,
00925 PSafetyMode mode = PSafeReference
00926 ) {
00927 PWaitAndSignal mutex(collectionMutex);
00928 if (PAssert(collection->GetObjectsIndex(obj) == P_MAX_INDEX, "Cannot insert safe object twice") &&
00929 obj->SafeReference())
00930 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00931 return NULL;
00932 }
00933
00942 virtual PBoolean Remove(
00943 Base * obj
00944 ) {
00945 return SafeRemove(obj);
00946 }
00947
00956 virtual PBoolean RemoveAt(
00957 PINDEX idx
00958 ) {
00959 return SafeRemoveAt(idx);
00960 }
00961
00967 virtual PSafePtr<Base> GetAt(
00968 PINDEX idx,
00969 PSafetyMode mode = PSafeReadWrite
00970 ) {
00971 return PSafePtr<Base>(*this, mode, idx);
00972 }
00973
00979 virtual PSafePtr<Base> FindWithLock(
00980 const Base & value,
00981 PSafetyMode mode = PSafeReadWrite
00982 ) {
00983 collectionMutex.Wait();
00984 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00985 collectionMutex.Signal();
00986 ptr.SetSafetyMode(mode);
00987 return ptr;
00988 }
00990 };
00991
00992
00997 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00998 {
00999 public:
01000 typedef PSafePtr<Base> value_type;
01001 };
01002
01003
01008 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
01009 {
01010 public:
01011 typedef PSafePtr<Base> value_type;
01012 };
01013
01014
01019 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
01020 {
01021 public:
01022 typedef PSafePtr<Base> value_type;
01023 };
01024
01025
01036 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
01037 {
01038 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
01039 public:
01044 PSafeDictionaryBase()
01045 : PSafeCollection(new Coll) { }
01047
01054 virtual void SetAt(const Key & key, Base * obj)
01055 {
01056 collectionMutex.Wait();
01057 SafeRemove(((Coll *)collection)->GetAt(key));
01058 if (PAssert(collection->GetObjectsIndex(obj) == P_MAX_INDEX, "Cannot insert safe object twice") &&
01059 obj->SafeReference())
01060 ((Coll *)collection)->SetAt(key, obj);
01061 collectionMutex.Signal();
01062 }
01063
01072 virtual PBoolean RemoveAt(
01073 const Key & key
01074 ) {
01075 PWaitAndSignal mutex(collectionMutex);
01076 return SafeRemove(((Coll *)collection)->GetAt(key));
01077 }
01078
01081 virtual PBoolean Contains(
01082 const Key & key
01083 ) {
01084 PWaitAndSignal lock(collectionMutex);
01085 return ((Coll *)collection)->Contains(key);
01086 }
01087
01093 virtual PSafePtr<Base> GetAt(
01094 PINDEX idx,
01095 PSafetyMode mode = PSafeReadWrite
01096 ) {
01097 return PSafePtr<Base>(*this, mode, idx);
01098 }
01099
01105 virtual PSafePtr<Base> FindWithLock(
01106 const Key & key,
01107 PSafetyMode mode = PSafeReadWrite
01108 ) {
01109 collectionMutex.Wait();
01110 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01111 collectionMutex.Signal();
01112 ptr.SetSafetyMode(mode);
01113 return ptr;
01114 }
01116 };
01117
01118
01123 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01124 {
01125 public:
01126 typedef PSafePtr<Base> value_type;
01127 };
01128
01129
01130 #endif // PTLIB_SAFE_COLLECTION_H
01131
01132
01133