1/* 2 * Python bindings. 3 * 4 * Open Phone Abstraction Library (OPAL) 5 * 6 * Copyright (c) 2011 Demetrius Cassidy 7 * 8 * The contents of this file are subject to the Mozilla Public License 9 * Version 1.0 (the "License"); you may not use this file except in 10 * compliance with the License. You may obtain a copy of the License at 11 * http://www.mozilla.org/MPL/ 12 * 13 * Software distributed under the License is distributed on an "AS IS" 14 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15 * the License for the specific language governing rights and limitations 16 * under the License. 17 * 18 * The Original Code is Open Phone Abstraction Library (OPAL) 19 * 20 * The Initial Developer of the Original Code is Demetrius Cassidy 21 * 22 * Contributor(s): ______________________________________. 23 * 24 * $Revision: 26117 $ 25 * $Author: rjongbloed $ 26 * $Date: 2011-07-04 22:45:05 -0500 (Mon, 04 Jul 2011) $ 27 */ 28 29%ModuleHeaderCode 30#include <ptlib.h> 31#include <ptlib/safecoll.h> 32%End 33 34 35/** This class defines a thread-safe object in a collection. 36 37 This is part of a set of classes to solve the general problem of a 38 collection (eg a PList or PDictionary) of objects that needs to be a made 39 thread safe. Any thread can add, read, write or remove an object with both 40 the object and the database of objects itself kept thread safe. 41 42 The act of adding a new object is simple and only requires locking the 43 collection itself during the add. 44 45 Locating an object is more complicated. The obvious lock on the collection 46 is made for the initial search. But we wish to have the full collection lock 47 for as short a period as possible (for performance reasons) so we lock the 48 individual object and release the lock on the collection. 49 50 A simple mutex on the object however is very dangerous as it can be (and 51 should be able to be!) locked from other threads independently of the 52 collection. If one of these threads subsequently needs to get at the 53 collection (eg it wants to remove the object) then we will have a deadlock. 54 Also, to avoid a race condition with the object begin deleted, the objects 55 lock must be made while the collection lock is set. The performance gains 56 are then lost as if something has the object locked for a long time, then 57 another object wanting that object will actually lock the collection for a 58 long time as well. 59 60 So, an object has 4 states: unused, referenced, reading & writing. With the 61 additional rider of "being removed". This flag prevents new locks from being 62 acquired and waits for all locks to be relinquished before removing the 63 object from the system. This prevents numerous race conditions and accesses 64 to deleted objects. 65 66 The "unused" state indicates the object exists in the collection but no 67 threads anywhere is using it. It may be moved to any state by any thread 68 while in this state. An object cannot be deleted (ie memory deallocated) 69 until it is unused. 70 71 The "referenced" state indicates that a thread has a reference (eg pointer) 72 to the object and it should not be deleted. It may be locked for reading or 73 writing at any time thereafter. 74 75 The "reading" state is a form of lock that indicates that a thread is 76 reading from the object but not writing. Multiple threads can obtain a read 77 lock. Note the read lock has an implicit "reference" state in it. 78 79 The "writing" state is a form of lock where the data in the object may 80 be changed. It can only be obtained exclusively and if there are no read 81 locks present. Again there is an implicit reference state in this lock. 82 83 Note that threads going to the "referenced" state may do so regardless of 84 the read or write locks present. 85 86 Access to safe objects (especially when in a safe collection) is recommended 87 to by the PSafePtr<> class which will manage reference counting and the 88 automatic unlocking of objects ones the pointer goes out of scope. It may 89 also be used to lock each object of a collection in turn. 90 91 The enumeration 92 */ 93class PSafeObject : PObject /NoDefaultCtors/ 94{ 95 public: 96 /**@name Construction */ 97 //@{ 98 /**Create a thread safe object. 99 */ 100 PSafeObject( 101 PSafeObject * indirectLock = NULL ///< Other safe object to be locked when this is locked 102 ); 103 //@} 104 105 /**@name Operations */ 106 //@{ 107 /**Increment the reference count for object. 108 This will guarantee that the object is not deleted (ie memory 109 deallocated) as the caller thread is using the object, but not 110 necessarily at this time locking it. 111 112 If the function returns PFalse, then the object has been flagged for 113 deletion and the calling thread should immediately cease using the 114 object. 115 116 A typical use of this would be when an entity (eg a thread) has a 117 pointer to the object but is not currenty accessing the objects data. 118 The LockXXX functions may be called independetly of the reference 119 system and the pointer beiong used for the LockXXX call is guaranteed 120 to be usable. 121 122 It is recommended that the PSafePtr<> class is used to manage this 123 rather than the application calling this function directly. 124 */ 125 PBoolean SafeReference(); 126 127 /**Decrement the reference count for object. 128 This indicates that the thread no longer has anything to do with the 129 object and it may be deleted (ie memory deallocated). 130 131 It is recommended that the PSafePtr<> class is used to manage this 132 rather than the application calling this function directly. 133 134 @return PTrue if reference count has reached zero and is not being 135 safely deleted elsewhere ie SafeRemove() not called 136 */ 137 PBoolean SafeDereference(); 138 139 /**Lock the object for Read Only access. 140 This will lock the object in read only mode. Multiple threads may lock 141 the object read only, but only one thread can lock for read/write. 142 Also, no read only threads can be present for the read/write lock to 143 occur and no read/write lock can be present for any read only locks to 144 occur. 145 146 If the function returns PFalse, then the object has been flagged for 147 deletion and the calling thread should immediately cease use of the 148 object, possibly executing the SafeDereference() function to remove 149 any references it may have acquired. 150 151 It is expected that the caller had already called the SafeReference() 152 function (directly or implicitly) before calling this function. It is 153 recommended that the PSafePtr<> class is used to automatically manage 154 the reference counting and locking of objects. 155 */ 156 PBoolean LockReadOnly() const; 157 158 /**Release the read only lock on an object. 159 Unlock the read only mutex that a thread had obtained. Multiple threads 160 may lock the object read only, but only one thread can lock for 161 read/write. Also, no read only threads can be present for the 162 read/write lock to occur and no read/write lock can be present for any 163 read only locks to occur. 164 165 It is recommended that the PSafePtr<> class is used to automatically 166 manage the reference counting and unlocking of objects. 167 */ 168 void UnlockReadOnly() const; 169 170 /**Lock the object for Read/Write access. 171 This will lock the object in read/write mode. Multiple threads may lock 172 the object read only, but only one thread can lock for read/write. 173 Also no read only threads can be present for the read/write lock to 174 occur and no read/write lock can be present for any read only locks to 175 occur. 176 177 If the function returns PFalse, then the object has been flagged for 178 deletion and the calling thread should immediately cease use of the 179 object, possibly executing the SafeDereference() function to remove 180 any references it may have acquired. 181 182 It is expected that the caller had already called the SafeReference() 183 function (directly or implicitly) before calling this function. It is 184 recommended that the PSafePtr<> class is used to automatically manage 185 the reference counting and locking of objects. 186 */ 187 PBoolean LockReadWrite(); 188 189 /**Release the read/write lock on an object. 190 Unlock the read/write mutex that a thread had obtained. Multiple threads 191 may lock the object read only, but only one thread can lock for 192 read/write. Also, no read only threads can be present for the 193 read/write lock to occur and no read/write lock can be present for any 194 read only locks to occur. 195 196 It is recommended that the PSafePtr<> class is used to automatically 197 manage the reference counting and unlocking of objects. 198 */ 199 void UnlockReadWrite(); 200 201 /**Set the removed flag. 202 This flags the object as beeing removed but does not physically delete 203 the memory being used by it. The SafelyCanBeDeleted() can then be used 204 to determine when all references to the object have been released so it 205 may be safely deleted. 206 207 This is typically used by the PSafeCollection class and is not expected 208 to be used directly by an application. 209 */ 210 void SafeRemove(); 211 212 /**Determine if the object can be safely deleted. 213 This determines if the object has been flagged for deletion and all 214 references to it have been released. 215 216 This is typically used by the PSafeCollection class and is not expected 217 to be used directly by an application. 218 */ 219 PBoolean SafelyCanBeDeleted() const; 220 221 /**Do any garbage collection that may be required by the object so that it 222 may be finally deleted. This is especially useful if there a references 223 back to this object which this object is in charge of disposing of. This 224 reference "glare" is to be resolved by this function being called every 225 time the owner collection is cleaning up, causing a cascade of clean ups 226 that might need to be required. 227 228 Default implementation simply returns true. 229 230 @return true if object may be deleted. 231 */ 232 virtual bool GarbageCollection(); 233 //@} 234 235};