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 #ifndef _SAFE_COLLECTION_H
00092 #define _SAFE_COLLECTION_H
00093
00094 #ifdef P_USE_PRAGMA
00095 #pragma interface
00096 #endif
00097
00098
00157 class PSafeObject : public PObject
00158 {
00159 PCLASSINFO(PSafeObject, PObject);
00160 public:
00165 PSafeObject();
00167
00188 BOOL SafeReference();
00189
00197 void SafeDereference();
00198
00216 BOOL LockReadOnly() const;
00217
00228 void UnlockReadOnly() const;
00229
00247 BOOL LockReadWrite();
00248
00259 void UnlockReadWrite();
00260
00270 void SafeRemove();
00271
00279 BOOL SafelyCanBeDeleted() const;
00281
00282 protected:
00283 mutable PMutex safetyMutex;
00284 unsigned safeReferenceCount;
00285 BOOL safelyBeingRemoved;
00286 mutable PReadWriteMutex safeInUseFlag;
00287 };
00288
00289
00292 class PSafeLockReadOnly
00293 {
00294 public:
00295 PSafeLockReadOnly(const PSafeObject & object);
00296 ~PSafeLockReadOnly();
00297 BOOL Lock();
00298 void Unlock();
00299 BOOL IsLocked() const { return locked; }
00300 bool operator!() const { return !locked; }
00301
00302 protected:
00303 PSafeObject & safeObject;
00304 BOOL locked;
00305 };
00306
00307
00308
00311 class PSafeLockReadWrite
00312 {
00313 public:
00314 PSafeLockReadWrite(const PSafeObject & object);
00315 ~PSafeLockReadWrite();
00316 BOOL Lock();
00317 void Unlock();
00318 BOOL IsLocked() const { return locked; }
00319 bool operator!() const { return !locked; }
00320
00321 protected:
00322 PSafeObject & safeObject;
00323 BOOL locked;
00324 };
00325
00326
00327
00340 class PSafeCollection : public PObject
00341 {
00342 PCLASSINFO(PSafeCollection, PObject);
00343 public:
00349 PSafeCollection(
00350 PCollection * collection
00351 );
00352
00356 ~PSafeCollection();
00358
00361 protected:
00370 virtual BOOL SafeRemove(
00371 PSafeObject * obj
00372 );
00373
00382 virtual BOOL SafeRemoveAt(
00383 PINDEX idx
00384 );
00385
00386 public:
00389 virtual void RemoveAll(
00390 BOOL synchronous = FALSE
00391 );
00392
00397 void AllowDeleteObjects(
00398 BOOL yes = TRUE
00399 ) { deleteObjects = yes; }
00400
00405 void DisallowDeleteObjects() { deleteObjects = FALSE; }
00406
00411 virtual BOOL DeleteObjectsToBeRemoved();
00412
00415 virtual void DeleteObject(PObject * object) const;
00416
00419 virtual void SetAutoDeleteObjects();
00420
00425 PINDEX GetSize() const;
00426
00431 BOOL IsEmpty() const { return GetSize() == 0; }
00432
00435 const PMutex & GetMutex() const { return collectionMutex; }
00437
00438 protected:
00439 void SafeRemoveObject(PSafeObject * obj);
00440 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00441
00442 PCollection * collection;
00443 mutable PMutex collectionMutex;
00444 BOOL deleteObjects;
00445 PList<PSafeObject> toBeRemoved;
00446 PMutex removalMutex;
00447 PTimer deleteObjectsTimer;
00448
00449 friend class PSafePtrBase;
00450 };
00451
00452
00453 enum PSafetyMode {
00454 PSafeReference,
00455 PSafeReadOnly,
00456 PSafeReadWrite
00457 };
00458
00474 class PSafePtrBase : public PObject
00475 {
00476 PCLASSINFO(PSafePtrBase, PObject);
00477
00480 protected:
00488 PSafePtrBase(
00489 PSafeObject * obj = NULL,
00490 PSafetyMode mode = PSafeReference
00491 );
00492
00500 PSafePtrBase(
00501 const PSafeCollection & safeCollection,
00502 PSafetyMode mode,
00503 PINDEX idx
00504 );
00505
00513 PSafePtrBase(
00514 const PSafeCollection & safeCollection,
00515 PSafetyMode mode,
00516 PSafeObject * obj
00517 );
00518
00524 PSafePtrBase(
00525 const PSafePtrBase & enumerator
00526 );
00527
00528 public:
00531 ~PSafePtrBase();
00533
00540 Comparison Compare(
00541 const PObject & obj
00542 ) const;
00544
00549 bool operator!() const { return currentObject == NULL; }
00550
00553 PSafetyMode GetSafetyMode() const { return lockMode; }
00554
00557 BOOL SetSafetyMode(
00558 PSafetyMode mode
00559 );
00560
00563 const PSafeCollection * GetCollection() const { return collection; }
00565
00566 void Assign(const PSafePtrBase & ptr);
00567 void Assign(const PSafeCollection & safeCollection);
00568 void Assign(PSafeObject * obj);
00569 void Assign(PINDEX idx);
00570
00571 protected:
00572 void Next();
00573 void Previous();
00574
00575 enum EnterSafetyModeOption {
00576 WithReference,
00577 AlreadyReferenced
00578 };
00579 BOOL EnterSafetyMode(EnterSafetyModeOption ref);
00580
00581 enum ExitSafetyModeOption {
00582 WithDereference,
00583 NoDereference
00584 };
00585 void ExitSafetyMode(ExitSafetyModeOption ref);
00586
00587 protected:
00588 const PSafeCollection * collection;
00589 PSafeObject * currentObject;
00590 PSafetyMode lockMode;
00591 };
00592
00593
00615 template <class T> class PSafePtr : public PSafePtrBase
00616 {
00617 PCLASSINFO(PSafePtr, PSafePtrBase);
00618 public:
00628 PSafePtr(
00629 T * obj = NULL,
00630 PSafetyMode mode = PSafeReference
00631 ) : PSafePtrBase(obj, mode) { }
00632
00640 PSafePtr(
00641 const PSafeCollection & safeCollection,
00642 PSafetyMode mode = PSafeReadWrite,
00643 PINDEX idx = 0
00644 ) : PSafePtrBase(safeCollection, mode, idx) { }
00645
00653 PSafePtr(
00654 const PSafeCollection & safeCollection,
00655 PSafetyMode mode,
00656 PSafeObject * obj
00657 ) : PSafePtrBase(safeCollection, mode, obj) { }
00658
00664 PSafePtr(
00665 const PSafePtr & ptr
00666 ) : PSafePtrBase(ptr) { }
00667
00673 PSafePtr & operator=(const PSafePtr & ptr)
00674 {
00675 Assign(ptr);
00676 return *this;
00677 }
00678
00683 PSafePtr & operator=(const PSafeCollection & safeCollection)
00684 {
00685 Assign(safeCollection);
00686 return *this;
00687 }
00688
00704 PSafePtr & operator=(T * obj)
00705 {
00706 Assign(obj);
00707 return *this;
00708 }
00709
00719 PSafePtr & operator=(PINDEX idx)
00720 {
00721 Assign(idx);
00722 return *this;
00723 }
00725
00730 operator T*() const { return (T *)currentObject; }
00731
00734 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00735
00738 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00739
00744 T * operator++(int)
00745 {
00746 T * previous = (T *)currentObject;
00747 Next();
00748 return previous;
00749 }
00750
00755 T * operator++()
00756 {
00757 Next();
00758 return (T *)currentObject;
00759 }
00760
00765 T * operator--(int)
00766 {
00767 T * previous = (T *)currentObject;
00768 Previous();
00769 return previous;
00770 }
00771
00776 T * operator--()
00777 {
00778 Previous();
00779 return (T *)currentObject;
00780 }
00782
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 };
00798
00799
00803 template <class Base, class Derived>
00804 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00805 {
00806
00807 PSafePtr<Derived> newPtr;
00808 Base * realPtr = oldPtr;
00809 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00810 newPtr.Assign(oldPtr);
00811 return newPtr;
00812 }
00813
00814
00825 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00826 {
00827 PCLASSINFO(PSafeColl, PSafeCollection);
00828 public:
00833 PSafeColl()
00834 : PSafeCollection(new Coll)
00835 { }
00837
00844 virtual PSafePtr<Base> Append(
00845 Base * obj,
00846 PSafetyMode mode = PSafeReference
00847 ) {
00848 PWaitAndSignal mutex(collectionMutex);
00849 if (!obj->SafeReference())
00850 return NULL;
00851 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00852 }
00853
00862 virtual BOOL Remove(
00863 Base * obj
00864 ) {
00865 return SafeRemove(obj);
00866 }
00867
00876 virtual BOOL RemoveAt(
00877 PINDEX idx
00878 ) {
00879 return SafeRemoveAt(idx);
00880 }
00881
00887 virtual PSafePtr<Base> GetAt(
00888 PINDEX idx,
00889 PSafetyMode mode = PSafeReadWrite
00890 ) {
00891 return PSafePtr<Base>(*this, mode, idx);
00892 }
00893
00899 virtual PSafePtr<Base> FindWithLock(
00900 const Base & value,
00901 PSafetyMode mode = PSafeReadWrite
00902 ) {
00903 collectionMutex.Wait();
00904 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00905 collectionMutex.Signal();
00906 ptr.SetSafetyMode(mode);
00907 return ptr;
00908 }
00910 };
00911
00912
00917 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00918 {
00919 };
00920
00921
00926 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00927 {
00928 };
00929
00930
00935 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00936 {
00937 };
00938
00939
00950 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00951 {
00952 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00953 public:
00958 PSafeDictionaryBase()
00959 : PSafeCollection(new Coll) { }
00961
00968 virtual void SetAt(const Key & key, Base * obj)
00969 {
00970 collectionMutex.Wait();
00971 SafeRemove(((Coll *)collection)->GetAt(key));
00972 if (obj->SafeReference())
00973 ((Coll *)collection)->SetAt(key, obj);
00974 collectionMutex.Signal();
00975 }
00976
00985 virtual BOOL RemoveAt(
00986 const Key & key
00987 ) {
00988 PWaitAndSignal mutex(collectionMutex);
00989 return SafeRemove(((Coll *)collection)->GetAt(key));
00990 }
00991
00994 virtual BOOL Contains(
00995 const Key & key
00996 ) {
00997 PWaitAndSignal lock(collectionMutex);
00998 return ((Coll *)collection)->Contains(key);
00999 }
01000
01006 virtual PSafePtr<Base> GetAt(
01007 PINDEX idx,
01008 PSafetyMode mode = PSafeReadWrite
01009 ) {
01010 return PSafePtr<Base>(*this, mode, idx);
01011 }
01012
01018 virtual PSafePtr<Base> FindWithLock(
01019 const Key & key,
01020 PSafetyMode mode = PSafeReadWrite
01021 ) {
01022 collectionMutex.Wait();
01023 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01024 collectionMutex.Signal();
01025 ptr.SetSafetyMode(mode);
01026 return ptr;
01027 }
01029 };
01030
01031
01036 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01037 {
01038 };
01039
01040
01041 #endif // _SAFE_COLLECTION_H
01042
01043