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
00435 class PSafePtrBase : public PObject
00436 {
00437 PCLASSINFO(PSafePtrBase, PObject);
00438
00441 protected:
00449 PSafePtrBase(
00450 PSafeObject * obj = NULL,
00451 PSafetyMode mode = PSafeReference
00452 );
00453
00461 PSafePtrBase(
00462 const PSafeCollection & safeCollection,
00463 PSafetyMode mode,
00464 PINDEX idx
00465 );
00466
00474 PSafePtrBase(
00475 const PSafeCollection & safeCollection,
00476 PSafetyMode mode,
00477 PSafeObject * obj
00478 );
00479
00485 PSafePtrBase(
00486 const PSafePtrBase & enumerator
00487 );
00488
00489 public:
00492 ~PSafePtrBase();
00494
00501 Comparison Compare(
00502 const PObject & obj
00503 ) const;
00505
00510 void SetNULL();
00511
00514 bool operator!() const { return currentObject == NULL; }
00515
00518 PSafetyMode GetSafetyMode() const { return lockMode; }
00519
00526 PBoolean SetSafetyMode(
00527 PSafetyMode mode
00528 );
00529
00532 const PSafeCollection * GetCollection() const { return collection; }
00534
00535 void Assign(const PSafePtrBase & ptr);
00536 void Assign(const PSafeCollection & safeCollection);
00537 void Assign(PSafeObject * obj);
00538 void Assign(PINDEX idx);
00539
00540 protected:
00541 void Next();
00542 void Previous();
00543
00544 enum EnterSafetyModeOption {
00545 WithReference,
00546 AlreadyReferenced
00547 };
00548 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00549
00550 enum ExitSafetyModeOption {
00551 WithDereference,
00552 NoDereference
00553 };
00554 void ExitSafetyMode(ExitSafetyModeOption ref);
00555
00556 protected:
00557 const PSafeCollection * collection;
00558 PSafeObject * currentObject;
00559 PSafetyMode lockMode;
00560 };
00561
00562
00584 template <class T> class PSafePtr : public PSafePtrBase
00585 {
00586 PCLASSINFO(PSafePtr, PSafePtrBase);
00587 public:
00597 PSafePtr(
00598 T * obj = NULL,
00599 PSafetyMode mode = PSafeReference
00600 ) : PSafePtrBase(obj, mode) { }
00601
00609 PSafePtr(
00610 const PSafeCollection & safeCollection,
00611 PSafetyMode mode = PSafeReadWrite,
00612 PINDEX idx = 0
00613 ) : PSafePtrBase(safeCollection, mode, idx) { }
00614
00622 PSafePtr(
00623 const PSafeCollection & safeCollection,
00624 PSafetyMode mode,
00625 PSafeObject * obj
00626 ) : PSafePtrBase(safeCollection, mode, obj) { }
00627
00633 PSafePtr(
00634 const PSafePtr & ptr
00635 ) : PSafePtrBase(ptr) { }
00636
00642 PSafePtr & operator=(const PSafePtr & ptr)
00643 {
00644 Assign(ptr);
00645 return *this;
00646 }
00647
00652 PSafePtr & operator=(const PSafeCollection & safeCollection)
00653 {
00654 Assign(safeCollection);
00655 return *this;
00656 }
00657
00673 PSafePtr & operator=(T * obj)
00674 {
00675 Assign(obj);
00676 return *this;
00677 }
00678
00688 PSafePtr & operator=(PINDEX idx)
00689 {
00690 Assign(idx);
00691 return *this;
00692 }
00694
00699 operator T*() const { return (T *)currentObject; }
00700
00703 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00704
00707 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00708
00713 T * operator++(int)
00714 {
00715 T * previous = (T *)currentObject;
00716 Next();
00717 return previous;
00718 }
00719
00724 T * operator++()
00725 {
00726 Next();
00727 return (T *)currentObject;
00728 }
00729
00734 T * operator--(int)
00735 {
00736 T * previous = (T *)currentObject;
00737 Previous();
00738 return previous;
00739 }
00740
00745 T * operator--()
00746 {
00747 Previous();
00748 return (T *)currentObject;
00749 }
00751
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 };
00767
00768
00772 template <class Base, class Derived>
00773 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00774 {
00775
00776 PSafePtr<Derived> newPtr;
00777 Base * realPtr = oldPtr;
00778 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00779 newPtr.Assign(oldPtr);
00780 return newPtr;
00781 }
00782
00783
00794 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00795 {
00796 PCLASSINFO(PSafeColl, PSafeCollection);
00797 public:
00802 PSafeColl()
00803 : PSafeCollection(new Coll)
00804 { }
00806
00813 virtual PSafePtr<Base> Append(
00814 Base * obj,
00815 PSafetyMode mode = PSafeReference
00816 ) {
00817 PWaitAndSignal mutex(collectionMutex);
00818 if (!obj->SafeReference())
00819 return NULL;
00820 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00821 }
00822
00831 virtual PBoolean Remove(
00832 Base * obj
00833 ) {
00834 return SafeRemove(obj);
00835 }
00836
00845 virtual PBoolean RemoveAt(
00846 PINDEX idx
00847 ) {
00848 return SafeRemoveAt(idx);
00849 }
00850
00856 virtual PSafePtr<Base> GetAt(
00857 PINDEX idx,
00858 PSafetyMode mode = PSafeReadWrite
00859 ) {
00860 return PSafePtr<Base>(*this, mode, idx);
00861 }
00862
00868 virtual PSafePtr<Base> FindWithLock(
00869 const Base & value,
00870 PSafetyMode mode = PSafeReadWrite
00871 ) {
00872 collectionMutex.Wait();
00873 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00874 collectionMutex.Signal();
00875 ptr.SetSafetyMode(mode);
00876 return ptr;
00877 }
00879 };
00880
00881
00886 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00887 {
00888 public:
00889 typedef PSafePtr<Base> value_type;
00890 };
00891
00892
00897 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00898 {
00899 public:
00900 typedef PSafePtr<Base> value_type;
00901 };
00902
00903
00908 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00909 {
00910 public:
00911 typedef PSafePtr<Base> value_type;
00912 };
00913
00914
00925 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00926 {
00927 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00928 public:
00933 PSafeDictionaryBase()
00934 : PSafeCollection(new Coll) { }
00936
00943 virtual void SetAt(const Key & key, Base * obj)
00944 {
00945 collectionMutex.Wait();
00946 SafeRemove(((Coll *)collection)->GetAt(key));
00947 if (obj->SafeReference())
00948 ((Coll *)collection)->SetAt(key, obj);
00949 collectionMutex.Signal();
00950 }
00951
00960 virtual PBoolean RemoveAt(
00961 const Key & key
00962 ) {
00963 PWaitAndSignal mutex(collectionMutex);
00964 return SafeRemove(((Coll *)collection)->GetAt(key));
00965 }
00966
00969 virtual PBoolean Contains(
00970 const Key & key
00971 ) {
00972 PWaitAndSignal lock(collectionMutex);
00973 return ((Coll *)collection)->Contains(key);
00974 }
00975
00981 virtual PSafePtr<Base> GetAt(
00982 PINDEX idx,
00983 PSafetyMode mode = PSafeReadWrite
00984 ) {
00985 return PSafePtr<Base>(*this, mode, idx);
00986 }
00987
00993 virtual PSafePtr<Base> FindWithLock(
00994 const Key & key,
00995 PSafetyMode mode = PSafeReadWrite
00996 ) {
00997 collectionMutex.Wait();
00998 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
00999 collectionMutex.Signal();
01000 ptr.SetSafetyMode(mode);
01001 return ptr;
01002 }
01004 };
01005
01006
01011 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01012 {
01013 public:
01014 typedef PSafePtr<Base> value_type;
01015 };
01016
01017
01018 #endif // PTLIB_SAFE_COLLECTION_H
01019
01020
01021