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 _SAFE_COLLECTION_H
00032 #define _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
00522 PBoolean SetSafetyMode(
00523 PSafetyMode mode
00524 );
00525
00528 const PSafeCollection * GetCollection() const { return collection; }
00530
00531 void Assign(const PSafePtrBase & ptr);
00532 void Assign(const PSafeCollection & safeCollection);
00533 void Assign(PSafeObject * obj);
00534 void Assign(PINDEX idx);
00535
00536 protected:
00537 void Next();
00538 void Previous();
00539
00540 enum EnterSafetyModeOption {
00541 WithReference,
00542 AlreadyReferenced
00543 };
00544 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00545
00546 enum ExitSafetyModeOption {
00547 WithDereference,
00548 NoDereference
00549 };
00550 void ExitSafetyMode(ExitSafetyModeOption ref);
00551
00552 protected:
00553 const PSafeCollection * collection;
00554 PSafeObject * currentObject;
00555 PSafetyMode lockMode;
00556 };
00557
00558
00580 template <class T> class PSafePtr : public PSafePtrBase
00581 {
00582 PCLASSINFO(PSafePtr, PSafePtrBase);
00583 public:
00593 PSafePtr(
00594 T * obj = NULL,
00595 PSafetyMode mode = PSafeReference
00596 ) : PSafePtrBase(obj, mode) { }
00597
00605 PSafePtr(
00606 const PSafeCollection & safeCollection,
00607 PSafetyMode mode = PSafeReadWrite,
00608 PINDEX idx = 0
00609 ) : PSafePtrBase(safeCollection, mode, idx) { }
00610
00618 PSafePtr(
00619 const PSafeCollection & safeCollection,
00620 PSafetyMode mode,
00621 PSafeObject * obj
00622 ) : PSafePtrBase(safeCollection, mode, obj) { }
00623
00629 PSafePtr(
00630 const PSafePtr & ptr
00631 ) : PSafePtrBase(ptr) { }
00632
00638 PSafePtr & operator=(const PSafePtr & ptr)
00639 {
00640 Assign(ptr);
00641 return *this;
00642 }
00643
00648 PSafePtr & operator=(const PSafeCollection & safeCollection)
00649 {
00650 Assign(safeCollection);
00651 return *this;
00652 }
00653
00669 PSafePtr & operator=(T * obj)
00670 {
00671 Assign(obj);
00672 return *this;
00673 }
00674
00684 PSafePtr & operator=(PINDEX idx)
00685 {
00686 Assign(idx);
00687 return *this;
00688 }
00690
00695 operator T*() const { return (T *)currentObject; }
00696
00699 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00700
00703 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00704
00709 T * operator++(int)
00710 {
00711 T * previous = (T *)currentObject;
00712 Next();
00713 return previous;
00714 }
00715
00720 T * operator++()
00721 {
00722 Next();
00723 return (T *)currentObject;
00724 }
00725
00730 T * operator--(int)
00731 {
00732 T * previous = (T *)currentObject;
00733 Previous();
00734 return previous;
00735 }
00736
00741 T * operator--()
00742 {
00743 Previous();
00744 return (T *)currentObject;
00745 }
00747
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 };
00763
00764
00768 template <class Base, class Derived>
00769 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00770 {
00771
00772 PSafePtr<Derived> newPtr;
00773 Base * realPtr = oldPtr;
00774 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00775 newPtr.Assign(oldPtr);
00776 return newPtr;
00777 }
00778
00779
00790 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00791 {
00792 PCLASSINFO(PSafeColl, PSafeCollection);
00793 public:
00798 PSafeColl()
00799 : PSafeCollection(new Coll)
00800 { }
00802
00809 virtual PSafePtr<Base> Append(
00810 Base * obj,
00811 PSafetyMode mode = PSafeReference
00812 ) {
00813 PWaitAndSignal mutex(collectionMutex);
00814 if (!obj->SafeReference())
00815 return NULL;
00816 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00817 }
00818
00827 virtual PBoolean Remove(
00828 Base * obj
00829 ) {
00830 return SafeRemove(obj);
00831 }
00832
00841 virtual PBoolean RemoveAt(
00842 PINDEX idx
00843 ) {
00844 return SafeRemoveAt(idx);
00845 }
00846
00852 virtual PSafePtr<Base> GetAt(
00853 PINDEX idx,
00854 PSafetyMode mode = PSafeReadWrite
00855 ) {
00856 return PSafePtr<Base>(*this, mode, idx);
00857 }
00858
00864 virtual PSafePtr<Base> FindWithLock(
00865 const Base & value,
00866 PSafetyMode mode = PSafeReadWrite
00867 ) {
00868 collectionMutex.Wait();
00869 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00870 collectionMutex.Signal();
00871 ptr.SetSafetyMode(mode);
00872 return ptr;
00873 }
00875 };
00876
00877
00882 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00883 {
00884 public:
00885 typedef PSafePtr<Base> value_type;
00886 };
00887
00888
00893 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00894 {
00895 public:
00896 typedef PSafePtr<Base> value_type;
00897 };
00898
00899
00904 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00905 {
00906 public:
00907 typedef PSafePtr<Base> value_type;
00908 };
00909
00910
00921 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00922 {
00923 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00924 public:
00929 PSafeDictionaryBase()
00930 : PSafeCollection(new Coll) { }
00932
00939 virtual void SetAt(const Key & key, Base * obj)
00940 {
00941 collectionMutex.Wait();
00942 SafeRemove(((Coll *)collection)->GetAt(key));
00943 if (obj->SafeReference())
00944 ((Coll *)collection)->SetAt(key, obj);
00945 collectionMutex.Signal();
00946 }
00947
00956 virtual PBoolean RemoveAt(
00957 const Key & key
00958 ) {
00959 PWaitAndSignal mutex(collectionMutex);
00960 return SafeRemove(((Coll *)collection)->GetAt(key));
00961 }
00962
00965 virtual PBoolean Contains(
00966 const Key & key
00967 ) {
00968 PWaitAndSignal lock(collectionMutex);
00969 return ((Coll *)collection)->Contains(key);
00970 }
00971
00977 virtual PSafePtr<Base> GetAt(
00978 PINDEX idx,
00979 PSafetyMode mode = PSafeReadWrite
00980 ) {
00981 return PSafePtr<Base>(*this, mode, idx);
00982 }
00983
00989 virtual PSafePtr<Base> FindWithLock(
00990 const Key & key,
00991 PSafetyMode mode = PSafeReadWrite
00992 ) {
00993 collectionMutex.Wait();
00994 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
00995 collectionMutex.Signal();
00996 ptr.SetSafetyMode(mode);
00997 return ptr;
00998 }
01000 };
01001
01002
01007 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01008 {
01009 public:
01010 typedef PSafePtr<Base> value_type;
01011 };
01012
01013
01014 #endif // _SAFE_COLLECTION_H
01015
01016