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 PBoolean safelyBeingRemoved;
00244 PReadWriteMutex safeInUseMutex;
00245 PReadWriteMutex * safeInUse;
00246 };
00247
00248
00251 class PSafeLockReadOnly
00252 {
00253 public:
00254 PSafeLockReadOnly(const PSafeObject & object);
00255 ~PSafeLockReadOnly();
00256 PBoolean Lock();
00257 void Unlock();
00258 PBoolean IsLocked() const { return locked; }
00259 bool operator!() const { return !locked; }
00260
00261 protected:
00262 PSafeObject & safeObject;
00263 PBoolean locked;
00264 };
00265
00266
00267
00270 class PSafeLockReadWrite
00271 {
00272 public:
00273 PSafeLockReadWrite(const PSafeObject & object);
00274 ~PSafeLockReadWrite();
00275 PBoolean Lock();
00276 void Unlock();
00277 PBoolean IsLocked() const { return locked; }
00278 bool operator!() const { return !locked; }
00279
00280 protected:
00281 PSafeObject & safeObject;
00282 PBoolean locked;
00283 };
00284
00285
00286
00299 class PSafeCollection : public PObject
00300 {
00301 PCLASSINFO(PSafeCollection, PObject);
00302 public:
00308 PSafeCollection(
00309 PCollection * collection
00310 );
00311
00315 ~PSafeCollection();
00317
00320 protected:
00329 virtual PBoolean SafeRemove(
00330 PSafeObject * obj
00331 );
00332
00341 virtual PBoolean SafeRemoveAt(
00342 PINDEX idx
00343 );
00344
00345 public:
00348 virtual void RemoveAll(
00349 PBoolean synchronous = PFalse
00350 );
00351
00356 void AllowDeleteObjects(
00357 PBoolean yes = PTrue
00358 ) { deleteObjects = yes; }
00359
00364 void DisallowDeleteObjects() { deleteObjects = PFalse; }
00365
00370 virtual PBoolean DeleteObjectsToBeRemoved();
00371
00374 virtual void DeleteObject(PObject * object) const;
00375
00378 virtual void SetAutoDeleteObjects();
00379
00384 PINDEX GetSize() const;
00385
00390 PBoolean IsEmpty() const { return GetSize() == 0; }
00391
00394 const PMutex & GetMutex() const { return collectionMutex; }
00396
00397 protected:
00398 void SafeRemoveObject(PSafeObject * obj);
00399 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00400
00401 PCollection * collection;
00402 mutable PMutex collectionMutex;
00403 PBoolean deleteObjects;
00404 PList<PSafeObject> toBeRemoved;
00405 PMutex removalMutex;
00406 PTimer deleteObjectsTimer;
00407
00408 friend class PSafePtrBase;
00409 };
00410
00411
00412 enum PSafetyMode {
00413 PSafeReference,
00414 PSafeReadOnly,
00415 PSafeReadWrite
00416 };
00417
00433 class PSafePtrBase : public PObject
00434 {
00435 PCLASSINFO(PSafePtrBase, PObject);
00436
00439 protected:
00447 PSafePtrBase(
00448 PSafeObject * obj = NULL,
00449 PSafetyMode mode = PSafeReference
00450 );
00451
00459 PSafePtrBase(
00460 const PSafeCollection & safeCollection,
00461 PSafetyMode mode,
00462 PINDEX idx
00463 );
00464
00472 PSafePtrBase(
00473 const PSafeCollection & safeCollection,
00474 PSafetyMode mode,
00475 PSafeObject * obj
00476 );
00477
00483 PSafePtrBase(
00484 const PSafePtrBase & enumerator
00485 );
00486
00487 public:
00490 ~PSafePtrBase();
00492
00499 Comparison Compare(
00500 const PObject & obj
00501 ) const;
00503
00508 void SetNULL();
00509
00512 bool operator!() const { return currentObject == NULL; }
00513
00516 PSafetyMode GetSafetyMode() const { return lockMode; }
00517
00520 PBoolean SetSafetyMode(
00521 PSafetyMode mode
00522 );
00523
00526 const PSafeCollection * GetCollection() const { return collection; }
00528
00529 void Assign(const PSafePtrBase & ptr);
00530 void Assign(const PSafeCollection & safeCollection);
00531 void Assign(PSafeObject * obj);
00532 void Assign(PINDEX idx);
00533
00534 protected:
00535 void Next();
00536 void Previous();
00537
00538 enum EnterSafetyModeOption {
00539 WithReference,
00540 AlreadyReferenced
00541 };
00542 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00543
00544 enum ExitSafetyModeOption {
00545 WithDereference,
00546 NoDereference
00547 };
00548 void ExitSafetyMode(ExitSafetyModeOption ref);
00549
00550 protected:
00551 const PSafeCollection * collection;
00552 PSafeObject * currentObject;
00553 PSafetyMode lockMode;
00554 };
00555
00556
00578 template <class T> class PSafePtr : public PSafePtrBase
00579 {
00580 PCLASSINFO(PSafePtr, PSafePtrBase);
00581 public:
00591 PSafePtr(
00592 T * obj = NULL,
00593 PSafetyMode mode = PSafeReference
00594 ) : PSafePtrBase(obj, mode) { }
00595
00603 PSafePtr(
00604 const PSafeCollection & safeCollection,
00605 PSafetyMode mode = PSafeReadWrite,
00606 PINDEX idx = 0
00607 ) : PSafePtrBase(safeCollection, mode, idx) { }
00608
00616 PSafePtr(
00617 const PSafeCollection & safeCollection,
00618 PSafetyMode mode,
00619 PSafeObject * obj
00620 ) : PSafePtrBase(safeCollection, mode, obj) { }
00621
00627 PSafePtr(
00628 const PSafePtr & ptr
00629 ) : PSafePtrBase(ptr) { }
00630
00636 PSafePtr & operator=(const PSafePtr & ptr)
00637 {
00638 Assign(ptr);
00639 return *this;
00640 }
00641
00646 PSafePtr & operator=(const PSafeCollection & safeCollection)
00647 {
00648 Assign(safeCollection);
00649 return *this;
00650 }
00651
00667 PSafePtr & operator=(T * obj)
00668 {
00669 Assign(obj);
00670 return *this;
00671 }
00672
00682 PSafePtr & operator=(PINDEX idx)
00683 {
00684 Assign(idx);
00685 return *this;
00686 }
00688
00693 operator T*() const { return (T *)currentObject; }
00694
00697 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00698
00701 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00702
00707 T * operator++(int)
00708 {
00709 T * previous = (T *)currentObject;
00710 Next();
00711 return previous;
00712 }
00713
00718 T * operator++()
00719 {
00720 Next();
00721 return (T *)currentObject;
00722 }
00723
00728 T * operator--(int)
00729 {
00730 T * previous = (T *)currentObject;
00731 Previous();
00732 return previous;
00733 }
00734
00739 T * operator--()
00740 {
00741 Previous();
00742 return (T *)currentObject;
00743 }
00745
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760 };
00761
00762
00766 template <class Base, class Derived>
00767 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00768 {
00769
00770 PSafePtr<Derived> newPtr;
00771 Base * realPtr = oldPtr;
00772 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00773 newPtr.Assign(oldPtr);
00774 return newPtr;
00775 }
00776
00777
00788 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00789 {
00790 PCLASSINFO(PSafeColl, PSafeCollection);
00791 public:
00796 PSafeColl()
00797 : PSafeCollection(new Coll)
00798 { }
00800
00807 virtual PSafePtr<Base> Append(
00808 Base * obj,
00809 PSafetyMode mode = PSafeReference
00810 ) {
00811 PWaitAndSignal mutex(collectionMutex);
00812 if (!obj->SafeReference())
00813 return NULL;
00814 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00815 }
00816
00825 virtual PBoolean Remove(
00826 Base * obj
00827 ) {
00828 return SafeRemove(obj);
00829 }
00830
00839 virtual PBoolean RemoveAt(
00840 PINDEX idx
00841 ) {
00842 return SafeRemoveAt(idx);
00843 }
00844
00850 virtual PSafePtr<Base> GetAt(
00851 PINDEX idx,
00852 PSafetyMode mode = PSafeReadWrite
00853 ) {
00854 return PSafePtr<Base>(*this, mode, idx);
00855 }
00856
00862 virtual PSafePtr<Base> FindWithLock(
00863 const Base & value,
00864 PSafetyMode mode = PSafeReadWrite
00865 ) {
00866 collectionMutex.Wait();
00867 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00868 collectionMutex.Signal();
00869 ptr.SetSafetyMode(mode);
00870 return ptr;
00871 }
00873 };
00874
00875
00880 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00881 {
00882 public:
00883 typedef PSafePtr<Base> value_type;
00884 };
00885
00886
00891 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00892 {
00893 public:
00894 typedef PSafePtr<Base> value_type;
00895 };
00896
00897
00902 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00903 {
00904 public:
00905 typedef PSafePtr<Base> value_type;
00906 };
00907
00908
00919 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00920 {
00921 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00922 public:
00927 PSafeDictionaryBase()
00928 : PSafeCollection(new Coll) { }
00930
00937 virtual void SetAt(const Key & key, Base * obj)
00938 {
00939 collectionMutex.Wait();
00940 SafeRemove(((Coll *)collection)->GetAt(key));
00941 if (obj->SafeReference())
00942 ((Coll *)collection)->SetAt(key, obj);
00943 collectionMutex.Signal();
00944 }
00945
00954 virtual PBoolean RemoveAt(
00955 const Key & key
00956 ) {
00957 PWaitAndSignal mutex(collectionMutex);
00958 return SafeRemove(((Coll *)collection)->GetAt(key));
00959 }
00960
00963 virtual PBoolean Contains(
00964 const Key & key
00965 ) {
00966 PWaitAndSignal lock(collectionMutex);
00967 return ((Coll *)collection)->Contains(key);
00968 }
00969
00975 virtual PSafePtr<Base> GetAt(
00976 PINDEX idx,
00977 PSafetyMode mode = PSafeReadWrite
00978 ) {
00979 return PSafePtr<Base>(*this, mode, idx);
00980 }
00981
00987 virtual PSafePtr<Base> FindWithLock(
00988 const Key & key,
00989 PSafetyMode mode = PSafeReadWrite
00990 ) {
00991 collectionMutex.Wait();
00992 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
00993 collectionMutex.Signal();
00994 ptr.SetSafetyMode(mode);
00995 return ptr;
00996 }
00998 };
00999
01000
01005 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
01006 {
01007 public:
01008 typedef PSafePtr<Base> value_type;
01009 };
01010
01011
01012 #endif // _SAFE_COLLECTION_H
01013
01014