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
#ifndef _SAFE_COLLECTION_H
00058
#define _SAFE_COLLECTION_H
00059
00060
#ifdef P_USE_PRAGMA
00061
#pragma interface
00062
#endif
00063
00064
00123 class PSafeObject :
public PObject
00124 {
00125
PCLASSINFO(
PSafeObject,
PObject);
00126
public:
00131
PSafeObject();
00133
00154 BOOL
SafeReference();
00155
00163
void SafeDereference();
00164
00182 BOOL
LockReadOnly()
const;
00183
00194
void UnlockReadOnly()
const;
00195
00213 BOOL
LockReadWrite();
00214
00225
void UnlockReadWrite();
00226
00236
void SafeRemove();
00237
00245 BOOL
SafelyCanBeDeleted();
00247
00248
protected:
00249 PMutex safetyMutex;
00250 unsigned safeReferenceCount;
00251 BOOL
safelyBeingRemoved;
00252 PReadWriteMutex safeInUseFlag;
00253 };
00254
00255
00268 class PSafeCollection :
public PObject
00269 {
00270
PCLASSINFO(
PSafeCollection,
PObject);
00271
public:
00277
PSafeCollection(
00278
PCollection *
collection
00279 );
00280
00284
~PSafeCollection();
00286
00289
protected:
00298
virtual BOOL
SafeRemove(
00299
PSafeObject * obj
00300 );
00301
00310
virtual BOOL
SafeRemoveAt(
00311 PINDEX idx
00312 );
00313
00314
public:
00317
virtual void RemoveAll();
00318
00321
virtual void DeleteObjectsToBeRemoved();
00322
00325
virtual void SetAutoDeleteObjects();
00326
00332 PINDEX
GetSize()
const {
return collection->
GetSize(); }
00333
00336 const PMutex &
GetMutex()
const {
return collectionMutex; }
00338
00339
protected:
00340
void SafeRemoveObject(
PSafeObject * obj);
00341
PDECLARE_NOTIFIER(
PTimer,
PSafeCollection, DeleteObjectsTimeout);
00342
00343 PCollection * collection;
00344 PMutex collectionMutex;
00345 PAbstractList toBeRemoved;
00346 PMutex removalMutex;
00347 PTimer deleteObjectsTimer;
00348
00349
friend class PSafePtrBase;
00350 };
00351
00352
00353 enum PSafetyMode {
00354
PSafeReference,
00355
PSafeReadOnly,
00356
PSafeReadWrite
00357 };
00358
00374 class PSafePtrBase :
public PObject
00375 {
00376
PCLASSINFO(
PSafePtrBase,
PObject);
00377
00380
protected:
00388
PSafePtrBase(
00389
PSafeObject * obj = NULL,
00390
PSafetyMode mode =
PSafeReference
00391 );
00392
00400
PSafePtrBase(
00401
PSafeCollection & safeCollection,
00402
PSafetyMode mode,
00403 PINDEX idx
00404 );
00405
00413
PSafePtrBase(
00414
PSafeCollection & safeCollection,
00415
PSafetyMode mode,
00416
PSafeObject * obj
00417 );
00418
00424
PSafePtrBase(
00425
const PSafePtrBase & enumerator
00426 );
00427
00428
public:
00431
~PSafePtrBase();
00433
00440 Comparison
Compare(
00441
const PObject & obj
00442 )
const;
00444
00447
public:
00450 BOOL
SetSafetyMode(
00451
PSafetyMode mode
00452 );
00453
00454
protected:
00455
void Assign(
const PSafePtrBase & enumerator);
00456
void Assign(
PSafeCollection & safeCollection);
00457
void Assign(
PSafeObject * obj);
00458
void Assign(PINDEX idx);
00459
void Next();
00460
void Previous();
00461
00462 enum EnterSafetyModeOption {
00463
WithReference,
00464
AlreadyReferenced
00465 };
00466 BOOL EnterSafetyMode(EnterSafetyModeOption ref);
00467
00468 enum ExitSafetyModeOption {
00469
WithDereference,
00470
NoDereference
00471 };
00472
void ExitSafetyMode(ExitSafetyModeOption ref);
00474
00475
protected:
00476 PSafeCollection *
collection;
00477 PSafeObject *
currentObject;
00478 PSafetyMode lockMode;
00479 };
00480
00481
00503 template <
class T>
class PSafePtr :
public PSafePtrBase
00504 {
00505
PCLASSINFO(
PSafePtr,
PSafePtrBase);
00506
public:
00516 PSafePtr(
00517 T * obj = NULL,
00518 PSafetyMode mode = PSafeReference
00519 ) :
PSafePtrBase(obj, mode) { }
00520
00528 PSafePtr(
00529
PSafeCollection & safeCollection,
00530 PSafetyMode mode = PSafeReadWrite,
00531 PINDEX idx = 0
00532 ) :
PSafePtrBase(safeCollection, mode, idx) { }
00533
00541 PSafePtr(
00542
PSafeCollection & safeCollection,
00543 PSafetyMode mode,
00544
PSafeObject * obj
00545 ) :
PSafePtrBase(safeCollection, mode, obj) { }
00546
00552 PSafePtr(
00553
const PSafePtr & enumerator
00554 ) :
PSafePtrBase(enumerator) { }
00555
00561 PSafePtr &
operator=(
const PSafePtr & enumerator)
00562 {
00563 Assign(enumerator);
00564
return *
this;
00565 }
00566
00571 PSafePtr &
operator=(
PSafeCollection & safeCollection)
00572 {
00573 Assign(safeCollection);
00574
return *
this;
00575 }
00576
00592 PSafePtr &
operator=(T * obj)
00593 {
00594 Assign(obj);
00595
return *
this;
00596 }
00597
00607 PSafePtr &
operator=(PINDEX idx)
00608 {
00609 Assign(idx);
00610
return *
this;
00611 }
00613
00618 operator T*() const {
return (T *)currentObject; }
00619
00622 T &
operator*() const {
return *(T *)
PAssertNULL(currentObject); }
00623
00626 T *
operator->()
const {
return (T *)
PAssertNULL(currentObject); }
00627
00632 T *
operator++(
int)
00633 {
00634 T * previous = (T *)currentObject;
00635
Next();
00636
return previous;
00637 }
00638
00643 T *
operator++()
00644 {
00645
Next();
00646
return (T *)currentObject;
00647 }
00648
00653 T *
operator--(
int)
00654 {
00655 T * previous = (T *)currentObject;
00656
Previous();
00657
return previous;
00658 }
00659
00664 T *
operator--()
00665 {
00666
Previous();
00667
return (T *)currentObject;
00668 }
00670 };
00671
00672
00683 template <
class Coll,
class Base>
class PSafeColl :
public PSafeCollection
00684 {
00685
PCLASSINFO(
PSafeColl,
PSafeCollection);
00686
public:
00691 PSafeColl()
00692 :
PSafeCollection(new Coll)
00693 { }
00695
00702 virtual PSafePtr<Base> Append(
00703 Base * obj,
00704 PSafetyMode mode = PSafeReference
00705 ) {
00706
PWaitAndSignal mutex(collectionMutex);
00707
return PSafePtr<Base>(*
this, mode, collection->
Append(obj));
00708 }
00709
00718 virtual BOOL Remove(
00719 Base * obj
00720 ) {
00721
return SafeRemove(obj);
00722 }
00723
00732 virtual BOOL RemoveAt(
00733 PINDEX idx
00734 ) {
00735
return SafeRemoveAt(idx);
00736 }
00737
00743 virtual PSafePtr<Base> GetWithLock(
00744 PINDEX idx,
00745 PSafetyMode mode = PSafeReadWrite
00746 ) {
00747
return PSafePtr<Base>(*
this, mode, idx);
00748 }
00749
00755 virtual PSafePtr<Base> FindWithLock(
00756
const Base & value,
00757 PSafetyMode mode = PSafeReadWrite
00758 ) {
00759 collectionMutex.
Wait();
00760
PSafePtr<Base> ptr(*
this,
PSafeReference, collection->
GetValuesIndex(value));
00761 collectionMutex.
Signal();
00762 ptr.
SetSafetyMode(mode);
00763
return ptr;
00764 }
00766 };
00767
00768
00773 template <
class Base>
class PSafeArray :
public PSafeColl<PArray<Base>, Base>
00774 {
00775 };
00776
00777
00782 template <
class Base>
class PSafeList :
public PSafeColl<PList<Base>, Base>
00783 {
00784 };
00785
00786
00791 template <
class Base>
class PSafeSortedList :
public PSafeColl<PSortedList<Base>, Base>
00792 {
00793 };
00794
00795
00806 template <
class Coll,
class Key,
class Base>
class PSafeDictionaryBase :
public PSafeCollection
00807 {
00808
PCLASSINFO(
PSafeDictionaryBase,
PSafeCollection);
00809
public:
00814 PSafeDictionaryBase()
00815 :
PSafeCollection(new Coll) { }
00817
00824 virtual void SetAt(
const Key & key, Base * obj)
00825 {
00826 collectionMutex.
Wait();
00827 SafeRemove(((Coll *)collection)->GetAt(key));
00828 ((Coll *)collection)->SetAt(key, obj);
00829 collectionMutex.
Signal();
00830 }
00831
00840 virtual BOOL RemoveAt(
00841
const Key & key
00842 ) {
00843
PWaitAndSignal mutex(collectionMutex);
00844
return SafeRemove(((Coll *)collection)->GetAt(key));
00845 }
00846
00852 virtual PSafePtr<Base> GetWithLock(
00853 PINDEX idx,
00854 PSafetyMode mode = PSafeReadWrite
00855 ) {
00856
return PSafePtr<Base>(*
this, mode, idx);
00857 }
00858
00864 virtual PSafePtr<Base> FindWithLock(
00865
const Key & key,
00866 PSafetyMode mode = PSafeReadWrite
00867 ) {
00868 collectionMutex.
Wait();
00869
PSafePtr<Base> ptr(*
this,
PSafeReference, ((Coll *)collection)->GetAt(key));
00870 collectionMutex.
Signal();
00871 ptr.
SetSafetyMode(mode);
00872
return ptr;
00873 }
00875 };
00876
00877
00882 template <
class Key,
class Base>
class PSafeDictionary :
public PSafeDictionaryBase<PDictionary<Key, Base>, Key, Base>
00883 {
00884 };
00885
00886
00887
#endif // _SAFE_COLLECTION_H
00888
00889