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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 #ifndef _SAFE_COLLECTION_H
00099 #define _SAFE_COLLECTION_H
00100
00101 #ifdef P_USE_PRAGMA
00102 #pragma interface
00103 #endif
00104
00105
00164 class PSafeObject : public PObject
00165 {
00166 PCLASSINFO(PSafeObject, PObject);
00167 public:
00172 PSafeObject(
00173 PSafeObject * indirectLock = NULL
00174 );
00176
00197 BOOL SafeReference();
00198
00206 void SafeDereference();
00207
00225 BOOL LockReadOnly() const;
00226
00237 void UnlockReadOnly() const;
00238
00256 BOOL LockReadWrite();
00257
00268 void UnlockReadWrite();
00269
00279 void SafeRemove();
00280
00288 BOOL SafelyCanBeDeleted() const;
00290
00291 private:
00292 mutable PMutex safetyMutex;
00293 unsigned safeReferenceCount;
00294 BOOL safelyBeingRemoved;
00295 PReadWriteMutex safeInUseMutex;
00296 PReadWriteMutex * safeInUse;
00297 };
00298
00299
00302 class PSafeLockReadOnly
00303 {
00304 public:
00305 PSafeLockReadOnly(const PSafeObject & object);
00306 ~PSafeLockReadOnly();
00307 BOOL Lock();
00308 void Unlock();
00309 BOOL IsLocked() const { return locked; }
00310 bool operator!() const { return !locked; }
00311
00312 protected:
00313 PSafeObject & safeObject;
00314 BOOL locked;
00315 };
00316
00317
00318
00321 class PSafeLockReadWrite
00322 {
00323 public:
00324 PSafeLockReadWrite(const PSafeObject & object);
00325 ~PSafeLockReadWrite();
00326 BOOL Lock();
00327 void Unlock();
00328 BOOL IsLocked() const { return locked; }
00329 bool operator!() const { return !locked; }
00330
00331 protected:
00332 PSafeObject & safeObject;
00333 BOOL locked;
00334 };
00335
00336
00337
00350 class PSafeCollection : public PObject
00351 {
00352 PCLASSINFO(PSafeCollection, PObject);
00353 public:
00359 PSafeCollection(
00360 PCollection * collection
00361 );
00362
00366 ~PSafeCollection();
00368
00371 protected:
00380 virtual BOOL SafeRemove(
00381 PSafeObject * obj
00382 );
00383
00392 virtual BOOL SafeRemoveAt(
00393 PINDEX idx
00394 );
00395
00396 public:
00399 virtual void RemoveAll(
00400 BOOL synchronous = FALSE
00401 );
00402
00407 void AllowDeleteObjects(
00408 BOOL yes = TRUE
00409 ) { deleteObjects = yes; }
00410
00415 void DisallowDeleteObjects() { deleteObjects = FALSE; }
00416
00421 virtual BOOL DeleteObjectsToBeRemoved();
00422
00425 virtual void DeleteObject(PObject * object) const;
00426
00429 virtual void SetAutoDeleteObjects();
00430
00435 PINDEX GetSize() const;
00436
00441 BOOL IsEmpty() const { return GetSize() == 0; }
00442
00445 const PMutex & GetMutex() const { return collectionMutex; }
00447
00448 protected:
00449 void SafeRemoveObject(PSafeObject * obj);
00450 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00451
00452 PCollection * collection;
00453 mutable PMutex collectionMutex;
00454 BOOL deleteObjects;
00455 PList<PSafeObject> toBeRemoved;
00456 PMutex removalMutex;
00457 PTimer deleteObjectsTimer;
00458
00459 friend class PSafePtrBase;
00460 };
00461
00462
00463 enum PSafetyMode {
00464 PSafeReference,
00465 PSafeReadOnly,
00466 PSafeReadWrite
00467 };
00468
00484 class PSafePtrBase : public PObject
00485 {
00486 PCLASSINFO(PSafePtrBase, PObject);
00487
00490 protected:
00498 PSafePtrBase(
00499 PSafeObject * obj = NULL,
00500 PSafetyMode mode = PSafeReference
00501 );
00502
00510 PSafePtrBase(
00511 const PSafeCollection & safeCollection,
00512 PSafetyMode mode,
00513 PINDEX idx
00514 );
00515
00523 PSafePtrBase(
00524 const PSafeCollection & safeCollection,
00525 PSafetyMode mode,
00526 PSafeObject * obj
00527 );
00528
00534 PSafePtrBase(
00535 const PSafePtrBase & enumerator
00536 );
00537
00538 public:
00541 ~PSafePtrBase();
00543
00550 Comparison Compare(
00551 const PObject & obj
00552 ) const;
00554
00559 bool operator!() const { return currentObject == NULL; }
00560
00563 PSafetyMode GetSafetyMode() const { return lockMode; }
00564
00567 BOOL SetSafetyMode(
00568 PSafetyMode mode
00569 );
00570
00573 const PSafeCollection * GetCollection() const { return collection; }
00575
00576 void Assign(const PSafePtrBase & ptr);
00577 void Assign(const PSafeCollection & safeCollection);
00578 void Assign(PSafeObject * obj);
00579 void Assign(PINDEX idx);
00580
00581 protected:
00582 void Next();
00583 void Previous();
00584
00585 enum EnterSafetyModeOption {
00586 WithReference,
00587 AlreadyReferenced
00588 };
00589 BOOL EnterSafetyMode(EnterSafetyModeOption ref);
00590
00591 enum ExitSafetyModeOption {
00592 WithDereference,
00593 NoDereference
00594 };
00595 void ExitSafetyMode(ExitSafetyModeOption ref);
00596
00597 protected:
00598 const PSafeCollection * collection;
00599 PSafeObject * currentObject;
00600 PSafetyMode lockMode;
00601 };
00602
00603
00625 template <class T> class PSafePtr : public PSafePtrBase
00626 {
00627 PCLASSINFO(PSafePtr, PSafePtrBase);
00628 public:
00638 PSafePtr(
00639 T * obj = NULL,
00640 PSafetyMode mode = PSafeReference
00641 ) : PSafePtrBase(obj, mode) { }
00642
00650 PSafePtr(
00651 const PSafeCollection & safeCollection,
00652 PSafetyMode mode = PSafeReadWrite,
00653 PINDEX idx = 0
00654 ) : PSafePtrBase(safeCollection, mode, idx) { }
00655
00663 PSafePtr(
00664 const PSafeCollection & safeCollection,
00665 PSafetyMode mode,
00666 PSafeObject * obj
00667 ) : PSafePtrBase(safeCollection, mode, obj) { }
00668
00674 PSafePtr(
00675 const PSafePtr & ptr
00676 ) : PSafePtrBase(ptr) { }
00677
00683 PSafePtr & operator=(const PSafePtr & ptr)
00684 {
00685 Assign(ptr);
00686 return *this;
00687 }
00688
00693 PSafePtr & operator=(const PSafeCollection & safeCollection)
00694 {
00695 Assign(safeCollection);
00696 return *this;
00697 }
00698
00714 PSafePtr & operator=(T * obj)
00715 {
00716 Assign(obj);
00717 return *this;
00718 }
00719
00729 PSafePtr & operator=(PINDEX idx)
00730 {
00731 Assign(idx);
00732 return *this;
00733 }
00735
00740 operator T*() const { return (T *)currentObject; }
00741
00744 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00745
00748 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00749
00754 T * operator++(int)
00755 {
00756 T * previous = (T *)currentObject;
00757 Next();
00758 return previous;
00759 }
00760
00765 T * operator++()
00766 {
00767 Next();
00768 return (T *)currentObject;
00769 }
00770
00775 T * operator--(int)
00776 {
00777 T * previous = (T *)currentObject;
00778 Previous();
00779 return previous;
00780 }
00781
00786 T * operator--()
00787 {
00788 Previous();
00789 return (T *)currentObject;
00790 }
00792
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807 };
00808
00809
00813 template <class Base, class Derived>
00814 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00815 {
00816
00817 PSafePtr<Derived> newPtr;
00818 Base * realPtr = oldPtr;
00819 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00820 newPtr.Assign(oldPtr);
00821 return newPtr;
00822 }
00823
00824
00835 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00836 {
00837 PCLASSINFO(PSafeColl, PSafeCollection);
00838 public:
00843 PSafeColl()
00844 : PSafeCollection(new Coll)
00845 { }
00847
00854 virtual PSafePtr<Base> Append(
00855 Base * obj,
00856 PSafetyMode mode = PSafeReference
00857 ) {
00858 PWaitAndSignal mutex(collectionMutex);
00859 if (!obj->SafeReference())
00860 return NULL;
00861 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00862 }
00863
00872 virtual BOOL Remove(
00873 Base * obj
00874 ) {
00875 return SafeRemove(obj);
00876 }
00877
00886 virtual BOOL RemoveAt(
00887 PINDEX idx
00888 ) {
00889 return SafeRemoveAt(idx);
00890 }
00891
00897 virtual PSafePtr<Base> GetAt(
00898 PINDEX idx,
00899 PSafetyMode mode = PSafeReadWrite
00900 ) {
00901 return PSafePtr<Base>(*this, mode, idx);
00902 }
00903
00909 virtual PSafePtr<Base> FindWithLock(
00910 const Base & value,
00911 PSafetyMode mode = PSafeReadWrite
00912 ) {
00913 collectionMutex.Wait();
00914 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00915 collectionMutex.Signal();
00916 ptr.SetSafetyMode(mode);
00917 return ptr;
00918 }
00920 };
00921
00922
00927 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00928 {
00929 };
00930
00931
00936 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00937 {
00938 };
00939
00940
00945 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00946 {
00947 };
00948
00949
00960 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00961 {
00962 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00963 public:
00968 PSafeDictionaryBase()
00969 : PSafeCollection(new Coll) { }
00971
00978 virtual void SetAt(const Key & key, Base * obj)
00979 {
00980 collectionMutex.Wait();
00981 SafeRemove(((Coll *)collection)->GetAt(key));
00982 if (obj->SafeReference())
00983 ((Coll *)collection)->SetAt(key, obj);
00984 collectionMutex.Signal();
00985 }
00986
00995 virtual BOOL RemoveAt(
00996 const Key & key
00997 ) {
00998 PWaitAndSignal mutex(collectionMutex);
00999 return SafeRemove(((Coll *)collection)->GetAt(key));
01000 }
01001
01004 virtual BOOL Contains(
01005 const Key & key
01006 ) {
01007 PWaitAndSignal lock(collectionMutex);
01008 return ((Coll *)collection)->Contains(key);
01009 }
01010
01016 virtual PSafePtr<Base> GetAt(
01017 PINDEX idx,
01018 PSafetyMode mode = PSafeReadWrite
01019 ) {
01020 return PSafePtr<Base>(*this, mode, idx);
01021 }
01022
01028 virtual PSafePtr<Base> FindWithLock(
01029 const Key & key,
01030 PSafetyMode mode = PSafeReadWrite
01031 ) {
01032 collectionMutex.Wait();
01033 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01034 collectionMutex.Signal();
01035 ptr.SetSafetyMode(mode);
01036 return ptr;
01037 }
01039 };
01040
01041
01046 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01047 {
01048 };
01049
01050
01051 #endif // _SAFE_COLLECTION_H
01052
01053