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 #ifndef _SAFE_COLLECTION_H
00089 #define _SAFE_COLLECTION_H
00090
00091 #ifdef P_USE_PRAGMA
00092 #pragma interface
00093 #endif
00094
00095
00154 class PSafeObject : public PObject
00155 {
00156 PCLASSINFO(PSafeObject, PObject);
00157 public:
00162 PSafeObject();
00164
00185 BOOL SafeReference();
00186
00194 void SafeDereference();
00195
00213 BOOL LockReadOnly() const;
00214
00225 void UnlockReadOnly() const;
00226
00244 BOOL LockReadWrite();
00245
00256 void UnlockReadWrite();
00257
00267 void SafeRemove();
00268
00276 BOOL SafelyCanBeDeleted() const;
00278
00279 protected:
00280 mutable PMutex safetyMutex;
00281 unsigned safeReferenceCount;
00282 BOOL safelyBeingRemoved;
00283 mutable PReadWriteMutex safeInUseFlag;
00284 };
00285
00286
00289 class PSafeLockReadOnly
00290 {
00291 public:
00292 PSafeLockReadOnly(const PSafeObject & object);
00293 ~PSafeLockReadOnly();
00294 BOOL Lock();
00295 void Unlock();
00296 BOOL IsLocked() const { return locked; }
00297 bool operator!() const { return !locked; }
00298
00299 protected:
00300 PSafeObject & safeObject;
00301 BOOL locked;
00302 };
00303
00304
00305
00308 class PSafeLockReadWrite
00309 {
00310 public:
00311 PSafeLockReadWrite(const PSafeObject & object);
00312 ~PSafeLockReadWrite();
00313 BOOL Lock();
00314 void Unlock();
00315 BOOL IsLocked() const { return locked; }
00316 bool operator!() const { return !locked; }
00317
00318 protected:
00319 PSafeObject & safeObject;
00320 BOOL locked;
00321 };
00322
00323
00324
00337 class PSafeCollection : public PObject
00338 {
00339 PCLASSINFO(PSafeCollection, PObject);
00340 public:
00346 PSafeCollection(
00347 PCollection * collection
00348 );
00349
00353 ~PSafeCollection();
00355
00358 protected:
00367 virtual BOOL SafeRemove(
00368 PSafeObject * obj
00369 );
00370
00379 virtual BOOL SafeRemoveAt(
00380 PINDEX idx
00381 );
00382
00383 public:
00386 virtual void RemoveAll(
00387 BOOL synchronous = FALSE
00388 );
00389
00394 void AllowDeleteObjects(
00395 BOOL yes = TRUE
00396 ) { deleteObjects = yes; }
00397
00402 void DisallowDeleteObjects() { deleteObjects = FALSE; }
00403
00408 virtual BOOL DeleteObjectsToBeRemoved();
00409
00412 virtual void DeleteObject(PObject * object) const;
00413
00416 virtual void SetAutoDeleteObjects();
00417
00422 PINDEX GetSize() const;
00423
00428 BOOL IsEmpty() const { return GetSize() == 0; }
00429
00432 const PMutex & GetMutex() const { return collectionMutex; }
00434
00435 protected:
00436 void SafeRemoveObject(PSafeObject * obj);
00437 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00438
00439 PCollection * collection;
00440 mutable PMutex collectionMutex;
00441 BOOL deleteObjects;
00442 PList<PSafeObject> toBeRemoved;
00443 PMutex removalMutex;
00444 PTimer deleteObjectsTimer;
00445
00446 friend class PSafePtrBase;
00447 };
00448
00449
00450 enum PSafetyMode {
00451 PSafeReference,
00452 PSafeReadOnly,
00453 PSafeReadWrite
00454 };
00455
00471 class PSafePtrBase : public PObject
00472 {
00473 PCLASSINFO(PSafePtrBase, PObject);
00474
00477 protected:
00485 PSafePtrBase(
00486 PSafeObject * obj = NULL,
00487 PSafetyMode mode = PSafeReference
00488 );
00489
00497 PSafePtrBase(
00498 const PSafeCollection & safeCollection,
00499 PSafetyMode mode,
00500 PINDEX idx
00501 );
00502
00510 PSafePtrBase(
00511 const PSafeCollection & safeCollection,
00512 PSafetyMode mode,
00513 PSafeObject * obj
00514 );
00515
00521 PSafePtrBase(
00522 const PSafePtrBase & enumerator
00523 );
00524
00525 public:
00528 ~PSafePtrBase();
00530
00537 Comparison Compare(
00538 const PObject & obj
00539 ) const;
00541
00546 bool operator!() const { return currentObject == NULL; }
00547
00550 PSafetyMode GetSafetyMode() const { return lockMode; }
00551
00554 BOOL SetSafetyMode(
00555 PSafetyMode mode
00556 );
00557
00560 const PSafeCollection * GetCollection() const { return collection; }
00562
00563 void Assign(const PSafePtrBase & ptr);
00564 void Assign(const PSafeCollection & safeCollection);
00565 void Assign(PSafeObject * obj);
00566 void Assign(PINDEX idx);
00567
00568 protected:
00569 void Next();
00570 void Previous();
00571
00572 enum EnterSafetyModeOption {
00573 WithReference,
00574 AlreadyReferenced
00575 };
00576 BOOL EnterSafetyMode(EnterSafetyModeOption ref);
00577
00578 enum ExitSafetyModeOption {
00579 WithDereference,
00580 NoDereference
00581 };
00582 void ExitSafetyMode(ExitSafetyModeOption ref);
00583
00584 protected:
00585 const PSafeCollection * collection;
00586 PSafeObject * currentObject;
00587 PSafetyMode lockMode;
00588 };
00589
00590
00612 template <class T> class PSafePtr : public PSafePtrBase
00613 {
00614 PCLASSINFO(PSafePtr, PSafePtrBase);
00615 public:
00625 PSafePtr(
00626 T * obj = NULL,
00627 PSafetyMode mode = PSafeReference
00628 ) : PSafePtrBase(obj, mode) { }
00629
00637 PSafePtr(
00638 const PSafeCollection & safeCollection,
00639 PSafetyMode mode = PSafeReadWrite,
00640 PINDEX idx = 0
00641 ) : PSafePtrBase(safeCollection, mode, idx) { }
00642
00650 PSafePtr(
00651 const PSafeCollection & safeCollection,
00652 PSafetyMode mode,
00653 PSafeObject * obj
00654 ) : PSafePtrBase(safeCollection, mode, obj) { }
00655
00661 PSafePtr(
00662 const PSafePtr & ptr
00663 ) : PSafePtrBase(ptr) { }
00664
00670 PSafePtr & operator=(const PSafePtr & ptr)
00671 {
00672 Assign(ptr);
00673 return *this;
00674 }
00675
00680 PSafePtr & operator=(const PSafeCollection & safeCollection)
00681 {
00682 Assign(safeCollection);
00683 return *this;
00684 }
00685
00701 PSafePtr & operator=(T * obj)
00702 {
00703 Assign(obj);
00704 return *this;
00705 }
00706
00716 PSafePtr & operator=(PINDEX idx)
00717 {
00718 Assign(idx);
00719 return *this;
00720 }
00722
00727 operator T*() const { return (T *)currentObject; }
00728
00731 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00732
00735 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00736
00741 T * operator++(int)
00742 {
00743 T * previous = (T *)currentObject;
00744 Next();
00745 return previous;
00746 }
00747
00752 T * operator++()
00753 {
00754 Next();
00755 return (T *)currentObject;
00756 }
00757
00762 T * operator--(int)
00763 {
00764 T * previous = (T *)currentObject;
00765 Previous();
00766 return previous;
00767 }
00768
00773 T * operator--()
00774 {
00775 Previous();
00776 return (T *)currentObject;
00777 }
00779
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 };
00795
00796
00800 template <class Base, class Derived>
00801 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00802 {
00803
00804 PSafePtr<Derived> newPtr;
00805 Base * realPtr = oldPtr;
00806 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00807 newPtr.Assign(oldPtr);
00808 return newPtr;
00809 }
00810
00811
00822 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00823 {
00824 PCLASSINFO(PSafeColl, PSafeCollection);
00825 public:
00830 PSafeColl()
00831 : PSafeCollection(new Coll)
00832 { }
00834
00841 virtual PSafePtr<Base> Append(
00842 Base * obj,
00843 PSafetyMode mode = PSafeReference
00844 ) {
00845 PWaitAndSignal mutex(collectionMutex);
00846 if (!obj->SafeReference())
00847 return NULL;
00848 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00849 }
00850
00859 virtual BOOL Remove(
00860 Base * obj
00861 ) {
00862 return SafeRemove(obj);
00863 }
00864
00873 virtual BOOL RemoveAt(
00874 PINDEX idx
00875 ) {
00876 return SafeRemoveAt(idx);
00877 }
00878
00884 virtual PSafePtr<Base> GetAt(
00885 PINDEX idx,
00886 PSafetyMode mode = PSafeReadWrite
00887 ) {
00888 return PSafePtr<Base>(*this, mode, idx);
00889 }
00890
00896 virtual PSafePtr<Base> FindWithLock(
00897 const Base & value,
00898 PSafetyMode mode = PSafeReadWrite
00899 ) {
00900 collectionMutex.Wait();
00901 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00902 collectionMutex.Signal();
00903 ptr.SetSafetyMode(mode);
00904 return ptr;
00905 }
00907 };
00908
00909
00914 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00915 {
00916 };
00917
00918
00923 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00924 {
00925 };
00926
00927
00932 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00933 {
00934 };
00935
00936
00947 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00948 {
00949 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00950 public:
00955 PSafeDictionaryBase()
00956 : PSafeCollection(new Coll) { }
00958
00965 virtual void SetAt(const Key & key, Base * obj)
00966 {
00967 collectionMutex.Wait();
00968 SafeRemove(((Coll *)collection)->GetAt(key));
00969 if (obj->SafeReference())
00970 ((Coll *)collection)->SetAt(key, obj);
00971 collectionMutex.Signal();
00972 }
00973
00982 virtual BOOL RemoveAt(
00983 const Key & key
00984 ) {
00985 PWaitAndSignal mutex(collectionMutex);
00986 return SafeRemove(((Coll *)collection)->GetAt(key));
00987 }
00988
00991 virtual BOOL Contains(
00992 const Key & key
00993 ) {
00994 PWaitAndSignal lock(collectionMutex);
00995 return ((Coll *)collection)->Contains(key);
00996 }
00997
01003 virtual PSafePtr<Base> GetAt(
01004 PINDEX idx,
01005 PSafetyMode mode = PSafeReadWrite
01006 ) {
01007 return PSafePtr<Base>(*this, mode, idx);
01008 }
01009
01015 virtual PSafePtr<Base> FindWithLock(
01016 const Key & key,
01017 PSafetyMode mode = PSafeReadWrite
01018 ) {
01019 collectionMutex.Wait();
01020 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
01021 collectionMutex.Signal();
01022 ptr.SetSafetyMode(mode);
01023 return ptr;
01024 }
01026 };
01027
01028
01033 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01034 {
01035 };
01036
01037
01038 #endif // _SAFE_COLLECTION_H
01039
01040