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};