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;
00226
00227 private:
00228 mutable PMutex safetyMutex;
00229 unsigned safeReferenceCount;
00230 PBoolean safelyBeingRemoved;
00231 PReadWriteMutex safeInUseMutex;
00232 PReadWriteMutex * safeInUse;
00233 };
00234
00235
00238 class PSafeLockReadOnly
00239 {
00240 public:
00241 PSafeLockReadOnly(const PSafeObject & object);
00242 ~PSafeLockReadOnly();
00243 PBoolean Lock();
00244 void Unlock();
00245 PBoolean IsLocked() const { return locked; }
00246 bool operator!() const { return !locked; }
00247
00248 protected:
00249 PSafeObject & safeObject;
00250 PBoolean locked;
00251 };
00252
00253
00254
00257 class PSafeLockReadWrite
00258 {
00259 public:
00260 PSafeLockReadWrite(const PSafeObject & object);
00261 ~PSafeLockReadWrite();
00262 PBoolean Lock();
00263 void Unlock();
00264 PBoolean IsLocked() const { return locked; }
00265 bool operator!() const { return !locked; }
00266
00267 protected:
00268 PSafeObject & safeObject;
00269 PBoolean locked;
00270 };
00271
00272
00273
00286 class PSafeCollection : public PObject
00287 {
00288 PCLASSINFO(PSafeCollection, PObject);
00289 public:
00295 PSafeCollection(
00296 PCollection * collection
00297 );
00298
00302 ~PSafeCollection();
00304
00307 protected:
00316 virtual PBoolean SafeRemove(
00317 PSafeObject * obj
00318 );
00319
00328 virtual PBoolean SafeRemoveAt(
00329 PINDEX idx
00330 );
00331
00332 public:
00335 virtual void RemoveAll(
00336 PBoolean synchronous = PFalse
00337 );
00338
00343 void AllowDeleteObjects(
00344 PBoolean yes = PTrue
00345 ) { deleteObjects = yes; }
00346
00351 void DisallowDeleteObjects() { deleteObjects = PFalse; }
00352
00357 virtual PBoolean DeleteObjectsToBeRemoved();
00358
00361 virtual void DeleteObject(PObject * object) const;
00362
00365 virtual void SetAutoDeleteObjects();
00366
00371 PINDEX GetSize() const;
00372
00377 PBoolean IsEmpty() const { return GetSize() == 0; }
00378
00381 const PMutex & GetMutex() const { return collectionMutex; }
00383
00384 protected:
00385 void SafeRemoveObject(PSafeObject * obj);
00386 PDECLARE_NOTIFIER(PTimer, PSafeCollection, DeleteObjectsTimeout);
00387
00388 PCollection * collection;
00389 mutable PMutex collectionMutex;
00390 PBoolean deleteObjects;
00391 PList<PSafeObject> toBeRemoved;
00392 PMutex removalMutex;
00393 PTimer deleteObjectsTimer;
00394
00395 friend class PSafePtrBase;
00396 };
00397
00398
00399 enum PSafetyMode {
00400 PSafeReference,
00401 PSafeReadOnly,
00402 PSafeReadWrite
00403 };
00404
00420 class PSafePtrBase : public PObject
00421 {
00422 PCLASSINFO(PSafePtrBase, PObject);
00423
00426 protected:
00434 PSafePtrBase(
00435 PSafeObject * obj = NULL,
00436 PSafetyMode mode = PSafeReference
00437 );
00438
00446 PSafePtrBase(
00447 const PSafeCollection & safeCollection,
00448 PSafetyMode mode,
00449 PINDEX idx
00450 );
00451
00459 PSafePtrBase(
00460 const PSafeCollection & safeCollection,
00461 PSafetyMode mode,
00462 PSafeObject * obj
00463 );
00464
00470 PSafePtrBase(
00471 const PSafePtrBase & enumerator
00472 );
00473
00474 public:
00477 ~PSafePtrBase();
00479
00486 Comparison Compare(
00487 const PObject & obj
00488 ) const;
00490
00495 bool operator!() const { return currentObject == NULL; }
00496
00499 PSafetyMode GetSafetyMode() const { return lockMode; }
00500
00503 PBoolean SetSafetyMode(
00504 PSafetyMode mode
00505 );
00506
00509 const PSafeCollection * GetCollection() const { return collection; }
00511
00512 void Assign(const PSafePtrBase & ptr);
00513 void Assign(const PSafeCollection & safeCollection);
00514 void Assign(PSafeObject * obj);
00515 void Assign(PINDEX idx);
00516
00517 protected:
00518 void Next();
00519 void Previous();
00520
00521 enum EnterSafetyModeOption {
00522 WithReference,
00523 AlreadyReferenced
00524 };
00525 PBoolean EnterSafetyMode(EnterSafetyModeOption ref);
00526
00527 enum ExitSafetyModeOption {
00528 WithDereference,
00529 NoDereference
00530 };
00531 void ExitSafetyMode(ExitSafetyModeOption ref);
00532
00533 protected:
00534 const PSafeCollection * collection;
00535 PSafeObject * currentObject;
00536 PSafetyMode lockMode;
00537 };
00538
00539
00561 template <class T> class PSafePtr : public PSafePtrBase
00562 {
00563 PCLASSINFO(PSafePtr, PSafePtrBase);
00564 public:
00574 PSafePtr(
00575 T * obj = NULL,
00576 PSafetyMode mode = PSafeReference
00577 ) : PSafePtrBase(obj, mode) { }
00578
00586 PSafePtr(
00587 const PSafeCollection & safeCollection,
00588 PSafetyMode mode = PSafeReadWrite,
00589 PINDEX idx = 0
00590 ) : PSafePtrBase(safeCollection, mode, idx) { }
00591
00599 PSafePtr(
00600 const PSafeCollection & safeCollection,
00601 PSafetyMode mode,
00602 PSafeObject * obj
00603 ) : PSafePtrBase(safeCollection, mode, obj) { }
00604
00610 PSafePtr(
00611 const PSafePtr & ptr
00612 ) : PSafePtrBase(ptr) { }
00613
00619 PSafePtr & operator=(const PSafePtr & ptr)
00620 {
00621 Assign(ptr);
00622 return *this;
00623 }
00624
00629 PSafePtr & operator=(const PSafeCollection & safeCollection)
00630 {
00631 Assign(safeCollection);
00632 return *this;
00633 }
00634
00650 PSafePtr & operator=(T * obj)
00651 {
00652 Assign(obj);
00653 return *this;
00654 }
00655
00665 PSafePtr & operator=(PINDEX idx)
00666 {
00667 Assign(idx);
00668 return *this;
00669 }
00671
00676 operator T*() const { return (T *)currentObject; }
00677
00680 T & operator*() const { return *(T *)PAssertNULL(currentObject); }
00681
00684 T * operator->() const { return (T *)PAssertNULL(currentObject); }
00685
00690 T * operator++(int)
00691 {
00692 T * previous = (T *)currentObject;
00693 Next();
00694 return previous;
00695 }
00696
00701 T * operator++()
00702 {
00703 Next();
00704 return (T *)currentObject;
00705 }
00706
00711 T * operator--(int)
00712 {
00713 T * previous = (T *)currentObject;
00714 Previous();
00715 return previous;
00716 }
00717
00722 T * operator--()
00723 {
00724 Previous();
00725 return (T *)currentObject;
00726 }
00728
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 };
00744
00745
00749 template <class Base, class Derived>
00750 PSafePtr<Derived> PSafePtrCast(const PSafePtr<Base> & oldPtr)
00751 {
00752
00753 PSafePtr<Derived> newPtr;
00754 Base * realPtr = oldPtr;
00755 if (realPtr != NULL && PIsDescendant(realPtr, Derived))
00756 newPtr.Assign(oldPtr);
00757 return newPtr;
00758 }
00759
00760
00771 template <class Coll, class Base> class PSafeColl : public PSafeCollection
00772 {
00773 PCLASSINFO(PSafeColl, PSafeCollection);
00774 public:
00779 PSafeColl()
00780 : PSafeCollection(new Coll)
00781 { }
00783
00790 virtual PSafePtr<Base> Append(
00791 Base * obj,
00792 PSafetyMode mode = PSafeReference
00793 ) {
00794 PWaitAndSignal mutex(collectionMutex);
00795 if (!obj->SafeReference())
00796 return NULL;
00797 return PSafePtr<Base>(*this, mode, collection->Append(obj));
00798 }
00799
00808 virtual PBoolean Remove(
00809 Base * obj
00810 ) {
00811 return SafeRemove(obj);
00812 }
00813
00822 virtual PBoolean RemoveAt(
00823 PINDEX idx
00824 ) {
00825 return SafeRemoveAt(idx);
00826 }
00827
00833 virtual PSafePtr<Base> GetAt(
00834 PINDEX idx,
00835 PSafetyMode mode = PSafeReadWrite
00836 ) {
00837 return PSafePtr<Base>(*this, mode, idx);
00838 }
00839
00845 virtual PSafePtr<Base> FindWithLock(
00846 const Base & value,
00847 PSafetyMode mode = PSafeReadWrite
00848 ) {
00849 collectionMutex.Wait();
00850 PSafePtr<Base> ptr(*this, PSafeReference, collection->GetValuesIndex(value));
00851 collectionMutex.Signal();
00852 ptr.SetSafetyMode(mode);
00853 return ptr;
00854 }
00856 };
00857
00858
00863 template <class Base> class PSafeArray : public PSafeColl<PArray<Base>, Base>
00864 {
00865 };
00866
00867
00872 template <class Base> class PSafeList : public PSafeColl<PList<Base>, Base>
00873 {
00874 };
00875
00876
00881 template <class Base> class PSafeSortedList : public PSafeColl<PSortedList<Base>, Base>
00882 {
00883 };
00884
00885
00896 template <class Coll, class Key, class Base> class PSafeDictionaryBase : public PSafeCollection
00897 {
00898 PCLASSINFO(PSafeDictionaryBase, PSafeCollection);
00899 public:
00904 PSafeDictionaryBase()
00905 : PSafeCollection(new Coll) { }
00907
00914 virtual void SetAt(const Key & key, Base * obj)
00915 {
00916 collectionMutex.Wait();
00917 SafeRemove(((Coll *)collection)->GetAt(key));
00918 if (obj->SafeReference())
00919 ((Coll *)collection)->SetAt(key, obj);
00920 collectionMutex.Signal();
00921 }
00922
00931 virtual PBoolean RemoveAt(
00932 const Key & key
00933 ) {
00934 PWaitAndSignal mutex(collectionMutex);
00935 return SafeRemove(((Coll *)collection)->GetAt(key));
00936 }
00937
00940 virtual PBoolean Contains(
00941 const Key & key
00942 ) {
00943 PWaitAndSignal lock(collectionMutex);
00944 return ((Coll *)collection)->Contains(key);
00945 }
00946
00952 virtual PSafePtr<Base> GetAt(
00953 PINDEX idx,
00954 PSafetyMode mode = PSafeReadWrite
00955 ) {
00956 return PSafePtr<Base>(*this, mode, idx);
00957 }
00958
00964 virtual PSafePtr<Base> FindWithLock(
00965 const Key & key,
00966 PSafetyMode mode = PSafeReadWrite
00967 ) {
00968 collectionMutex.Wait();
00969 PSafePtr<Base> ptr(*this, PSafeReference, ((Coll *)collection)->GetAt(key));
00970 collectionMutex.Signal();
00971 ptr.SetSafetyMode(mode);
00972 return ptr;
00973 }
00975 };
00976
00977
00982 template <class Key, class Base> class PSafeDictionary : public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
00983 {
00984 };
00985
00986
00987 #endif // _SAFE_COLLECTION_H
00988
00989