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
00099
00100 #ifndef _SAFE_COLLECTION_H
00101 #define _SAFE_COLLECTION_H
00102
00103 #ifdef P_USE_PRAGMA
00104 #pragma interface
00105 #endif
00106
00107
00166 class PSafeObject : public PObject
00167 {
00168 PCLASSINFO(PSafeObject, PObject);
00169 public:
00174 PSafeObject(
00175 PSafeObject * indirectLock = NULL
00176 );
00178
00199 BOOL SafeReference();
00200
00211 BOOL SafeDereference();
00212
00230 BOOL LockReadOnly() const;
00231
00242 void UnlockReadOnly() const;
00243
00261 BOOL LockReadWrite();
00262
00273 void UnlockReadWrite();
00274
00284 void SafeRemove();
00285
00293 BOOL SafelyCanBeDeleted() const;
00295
00296 private:
00297 mutable PMutex safetyMutex;
00298 unsigned safeReferenceCount;
00299 BOOL safelyBeingRemoved;
00300 PReadWriteMutex safeInUseMutex;
00301 PReadWriteMutex * safeInUse;
00302 };
00303
00304
00307 class PSafeLockReadOnly
00308 {
00309 public:
00310 PSafeLockReadOnly(const PSafeObject & object);
00311 ~PSafeLockReadOnly();
00312 BOOL Lock();
00313 void Unlock();
00314 BOOL IsLocked() const { return locked; }
00315 bool operator!() const { return !locked; }
00316
00317 protected:
00318 PSafeObject & safeObject;
00319 BOOL locked;
00320 };
00321
00322
00323
00326 class PSafeLockReadWrite
00327 {
00328 public:
00329 PSafeLockReadWrite(const PSafeObject & object);
00330 ~PSafeLockReadWrite();
00331 BOOL Lock();
00332 void Unlock();
00333 BOOL IsLocked() const { return locked; }
00334 bool operator!() const { return !locked; }
00335
00336 protected:
00337 PSafeObject & safeObject;
00338 BOOL locked;
00339 };
00340
00341
00342
00355 class PSafeCollection : public PObject
00356 {
00357 PCLASSINFO(PSafeCollection, PObject);
00358 public:
00364 PSafeCollection(
00365 PCollection * collection
00366 );
00367
00371 ~PSafeCollection();
00373
00376 protected:
00385 virtual BOOL SafeRemove(
00386 PSafeObject * obj
00387 );
00388
00397 virtual BOOL SafeRemoveAt(
00398 PINDEX idx
00399 );
00400
00401 public:
00404 virtual void RemoveAll(
00405 BOOL synchronous = FALSE
00406 );
00407
00412 void AllowDeleteObjects(
00413 BOOL yes = TRUE
00414 ) { deleteObjects = yes; }
00415
00420 void DisallowDeleteObjects() { deleteObjects = FALSE; }
00421
00426 virtual BOOL DeleteObjectsToBeRemoved();
00427
00430 virtual void DeleteObject(PObject * object) const;
00431
00434 virtual void SetAutoDeleteObjects();
00435
00440 PINDEX GetSize() const;
00441
00446 BOOL IsEmpty() const { return GetSize() == 0; }
00447
00450 const PMutex & GetMutex() const { return collectionMutex; }
00452
00453 protected:
00454 void SafeRemoveObject(PSafeObject * obj);
00455 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00456
00457 PCollection * collection;
00458 mutable PMutex collectionMutex;
00459 BOOL deleteObjects;
00460 PList<PSafeObject> toBeRemoved;
00461 PMutex removalMutex;
00462 PTimer deleteObjectsTimer;
00463
00464 friend class PSafePtrBase;
00465 };
00466
00467
00468 enum PSafetyMode {
00469 PSafeReference,
00470 PSafeReadOnly,
00471 PSafeReadWrite
00472 };
00473
00489 class PSafePtrBase : public PObject
00490 {
00491 PCLASSINFO(PSafePtrBase, PObject);
00492
00495 protected:
00503 PSafePtrBase(
00504 PSafeObject * obj = NULL,
00505 PSafetyMode mode = PSafeReference
00506 );
00507
00515 PSafePtrBase(
00516 const PSafeCollection & safeCollection,
00517 PSafetyMode mode,
00518 PINDEX idx
00519 );
00520
00528 PSafePtrBase(
00529 const PSafeCollection & safeCollection,
00530 PSafetyMode mode,
00531 PSafeObject * obj
00532 );
00533
00539 PSafePtrBase(
00540 const PSafePtrBase & enumerator
00541 );
00542
00543 public:
00546 ~PSafePtrBase();
00548
00555 Comparison Compare(
00556 const PObject & obj
00557 ) const;
00559
00564 bool operator!() const { return currentObject == NULL; }
00565
00568 PSafetyMode GetSafetyMode() const { return lockMode; }
00569
00572 BOOL SetSafetyMode(
00573 PSafetyMode mode
00574 );
00575
00578 const PSafeCollection * GetCollection() const { return collection; }
00580
00581 void Assign(const PSafePtrBase & ptr);
00582 void Assign(const PSafeCollection & safeCollection);
00583 void Assign(PSafeObject * obj);
00584 void Assign(PINDEX idx);
00585
00586 protected:
00587 void Next();
00588 void Previous();
00589
00590 enum EnterSafetyModeOption {
00591 WithReference,
00592 AlreadyReferenced
00593 };
00594 BOOL EnterSafetyMode(EnterSafetyModeOption ref);
00595
00596 enum ExitSafetyModeOption {
00597 WithDereference,
00598 NoDereference
00599 };
00600 void ExitSafetyMode(ExitSafetyModeOption ref);
00601
00602 protected:
00603 const PSafeCollection * collection;
00604 PSafeObject * currentObject;
00605 PSafetyMode lockMode;
00606 };
00607
00608
00630 template <class T> class PSafePtr : public PSafePtrBase
00631 {
00632 PCLASSINFO(PSafePtr, PSafePtrBase);
00633 public:
00643 PSafePtr(
00644 T * obj = NULL,
00645 PSafetyMode mode = PSafeReference
00646 ) : PSafePtrBase(obj, mode) { }
00647
00655 PSafePtr(
00656 const PSafeCollection & safeCollection,
00657 PSafetyMode mode = PSafeReadWrite,
00658 PINDEX idx = 0
00659 ) : PSafePtrBase(safeCollection, mode, idx) { }
00660
00668 PSafePtr(
00669 const PSafeCollection & safeCollection,
00670 PSafetyMode mode,
00671 PSafeObject * obj
00672 ) : PSafePtrBase(safeCollection, mode, obj) { }
00673
00679 PSafePtr(
00680 const PSafePtr & ptr
00681 ) : PSafePtrBase(ptr) { }
00682
00688 PSafePtr & operator=(const PSafePtr & ptr)
00689 {
00690 Assign(ptr);
00691 return *this;
00692 }
00693
00698 PSafePtr & operator=(const PSafeCollection & safeCollection)
00699 {
00700 Assign(safeCollection);
00701 return *this;
00702 }
00703
00719 PSafePtr & operator=(T * obj)
00720 {
00721 Assign(obj);
00722 return *this;
00723 }
00724
00734 PSafePtr & operator=(PINDEX idx)
00735 {
00736 Assign(idx);
00737 return *this;
00738 }
00740
00745 operator T*() const { return (T *)currentObject; }
00746
00749 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00750
00753 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00754
00759 T * operator++(int)
00760 {
00761 T * previous = (T *)currentObject;
00762 Next();
00763 return previous;
00764 }
00765
00770 T * operator++()
00771 {
00772 Next();
00773 return (T *)currentObject;
00774 }
00775
00780 T * operator--(int)
00781 {
00782 T * previous = (T *)currentObject;
00783 Previous();
00784 return previous;
00785 }
00786
00791 T * operator--()
00792 {
00793 Previous();
00794 return (T *)currentObject;
00795 }
00797
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 };
00813
00814
00818 template <class Base, class Derived>
00819 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00820 {
00821
00822 PSafePtr<Derived> newPtr;
00823 Base * realPtr = oldPtr;
00824 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00825 newPtr.Assign(oldPtr);
00826 return newPtr;
00827 }
00828
00829
00840 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00841 {
00842 PCLASSINFO(PSafeColl, PSafeCollection);
00843 public:
00848 PSafeColl()
00849 : PSafeCollection(new Coll)
00850 { }
00852
00859 virtual PSafePtr<Base> Append(
00860 Base * obj,
00861 PSafetyMode mode = PSafeReference
00862 ) {
00863 PWaitAndSignal mutex(collectionMutex);
00864 if (!obj->SafeReference())
00865 return NULL;
00866 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00867 }
00868
00877 virtual BOOL Remove(
00878 Base * obj
00879 ) {
00880 return SafeRemove(obj);
00881 }
00882
00891 virtual BOOL RemoveAt(
00892 PINDEX idx
00893 ) {
00894 return SafeRemoveAt(idx);
00895 }
00896
00902 virtual PSafePtr<Base> GetAt(
00903 PINDEX idx,
00904 PSafetyMode mode = PSafeReadWrite
00905 ) {
00906 return PSafePtr<Base>(*this, mode, idx);
00907 }
00908
00914 virtual PSafePtr<Base> FindWithLock(
00915 const Base & value,
00916 PSafetyMode mode = PSafeReadWrite
00917 ) {
00918 collectionMutex.Wait();
00919 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00920 collectionMutex.Signal();
00921 ptr.SetSafetyMode(mode);
00922 return ptr;
00923 }
00925 };
00926
00927
00932 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00933 {
00934 };
00935
00936
00941 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00942 {
00943 };
00944
00945
00950 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00951 {
00952 };
00953
00954
00965 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00966 {
00967 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00968 public:
00973 PSafeDictionaryBase()
00974 : PSafeCollection(new Coll) { }
00976
00983 virtual void SetAt(const Key & key, Base * obj)
00984 {
00985 collectionMutex.Wait();
00986 SafeRemove(((Coll *)collection)->GetAt(key));
00987 if (obj->SafeReference())
00988 ((Coll *)collection)->SetAt(key, obj);
00989 collectionMutex.Signal();
00990 }
00991
01000 virtual BOOL RemoveAt(
01001 const Key & key
01002 ) {
01003 PWaitAndSignal mutex(collectionMutex);
01004 return SafeRemove(((Coll *)collection)->GetAt(key));
01005 }
01006
01009 virtual BOOL Contains(
01010 const Key & key
01011 ) {
01012 PWaitAndSignal lock(collectionMutex);
01013 return ((Coll *)collection)->Contains(key);
01014 }
01015
01021 virtual PSafePtr<Base> GetAt(
01022 PINDEX idx,
01023 PSafetyMode mode = PSafeReadWrite
01024 ) {
01025 return PSafePtr<Base>(*this, mode, idx);
01026 }
01027
01033 virtual PSafePtr<Base> FindWithLock(
01034 const Key & key,
01035 PSafetyMode mode = PSafeReadWrite
01036 ) {
01037 collectionMutex.Wait();
01038 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01039 collectionMutex.Signal();
01040 ptr.SetSafetyMode(mode);
01041 return ptr;
01042 }
01044 };
01045
01046
01051 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01052 {
01053 };
01054
01055
01056 #endif // _SAFE_COLLECTION_H
01057
01058