Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

safecoll.h

Go to the documentation of this file.
00001 /* 00002 * safecoll.h 00003 * 00004 * Thread safe collection classes. 00005 * 00006 * Portable Windows Library 00007 * 00008 * Copyright (c) 2002 Equivalence Pty. Ltd. 00009 * 00010 * The contents of this file are subject to the Mozilla Public License 00011 * Version 1.0 (the "License"); you may not use this file except in 00012 * compliance with the License. You may obtain a copy of the License at 00013 * http://www.mozilla.org/MPL/ 00014 * 00015 * Software distributed under the License is distributed on an "AS IS" 00016 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 00017 * the License for the specific language governing rights and limitations 00018 * under the License. 00019 * 00020 * The Original Code is Portable Windows Library. 00021 * 00022 * The Initial Developer of the Original Code is Equivalence Pty. Ltd. 00023 * 00024 * Contributor(s): ______________________________________. 00025 * 00026 * $Log: safecoll.h,v $ 00027 * Revision 1.7 2002/12/10 07:36:57 robertj 00028 * Fixed possible deadlock in PSafeCollection find functions. 00029 * 00030 * Revision 1.6 2002/10/29 00:06:14 robertj 00031 * Changed template classes so things like PSafeList actually creates the 00032 * base collection class as well. 00033 * Allowed for the PSafeList::Append() to return a locked pointer to the 00034 * object just appended. 00035 * 00036 * Revision 1.5 2002/10/04 08:22:40 robertj 00037 * Changed read/write mutex so can be called by same thread without deadlock 00038 * removing the need to a lock count in safe pointer. 00039 * Added asserts if try and dereference a NULL safe pointer. 00040 * Added more documentation on behaviour. 00041 * 00042 * Revision 1.4 2002/09/16 01:08:59 robertj 00043 * Added #define so can select if #pragma interface/implementation is used on 00044 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan. 00045 * 00046 * Revision 1.3 2002/08/29 06:51:11 robertj 00047 * Added optimisiation, separate mutex for toBeRemoved list. 00048 * 00049 * Revision 1.2 2002/05/06 00:44:45 robertj 00050 * Made the lock/unlock read only const so can be used in const functions. 00051 * 00052 * Revision 1.1 2002/05/01 04:16:43 robertj 00053 * Added thread safe collection classes. 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

Generated on Sat Jul 24 15:35:56 2004 for PWLib by doxygen 1.3.7