PTLib
Version 2.14.3
|
This class defines a thread-safe object in a collection. More...
#include <safecoll.h>
Public Member Functions | |
Construction | |
PSafeObject (PSafeObject *indirectLock=NULL) | |
Create a thread safe object. More... | |
Operations | |
PBoolean | SafeReference () |
Increment the reference count for object. More... | |
PBoolean | SafeDereference () |
Decrement the reference count for object. More... | |
PBoolean | LockReadOnly () const |
Lock the object for Read Only access. More... | |
void | UnlockReadOnly () const |
Release the read only lock on an object. More... | |
PBoolean | LockReadWrite () |
Lock the object for Read/Write access. More... | |
void | UnlockReadWrite () |
Release the read/write lock on an object. More... | |
void | SafeRemove () |
Set the removed flag. More... | |
PBoolean | SafelyCanBeDeleted () const |
Determine if the object can be safely deleted. More... | |
virtual bool | GarbageCollection () |
Do any garbage collection that may be required by the object so that it may be finally deleted. More... | |
unsigned | GetSafeReferenceCount () const |
Get count of references to this object. More... | |
![]() | |
unsigned | GetTraceContextIdentifier () const |
Get PTRACE context identifier. More... | |
void | SetTraceContextIdentifier (unsigned id) |
void | GetTraceContextIdentifier (PObject &obj) |
void | GetTraceContextIdentifier (PObject *obj) |
void | SetTraceContextIdentifier (const PObject &obj) |
void | SetTraceContextIdentifier (const PObject *obj) |
virtual | ~PObject () |
virtual PObject * | Clone () const |
Create a copy of the class on the heap. More... | |
template<class CLS > | |
CLS * | CloneAs () const |
As for Clone() but converts to specified type. More... | |
virtual PINDEX | HashFunction () const |
This function yields a hash value required by the PDictionary class. More... | |
virtual const char * | GetClass (unsigned ancestor=0) const |
Get the current dynamic type of the object instance. More... | |
PBoolean | IsClass (const char *cls) const |
virtual PBoolean | InternalIsDescendant (const char *clsName) const |
Determine if the dynamic type of the current instance is a descendent of the specified class. More... | |
__inline const PObject * | PTraceObjectInstance () const |
virtual Comparison | Compare (const PObject &obj) const |
Compare the two objects and return their relative rank. More... | |
virtual Comparison | CompareObjectMemoryDirect (const PObject &obj) const |
Determine the byte wise comparison of two objects. More... | |
bool | operator== (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator!= (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator< (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator> (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator<= (const PObject &obj) const |
Compare the two objects. More... | |
bool | operator>= (const PObject &obj) const |
Compare the two objects. More... | |
virtual void | PrintOn (ostream &strm) const |
Output the contents of the object to the stream. More... | |
virtual void | ReadFrom (istream &strm) |
Input the contents of the object from the stream. More... | |
Additional Inherited Members | |
![]() | |
enum | Comparison { LessThan = -1, EqualTo = 0, GreaterThan = 1 } |
Result of the comparison operation performed by the Compare() function. More... | |
![]() | |
static const char * | Class () |
Get the name of the class as a C string. More... | |
static __inline const PObject * | PTraceObjectInstance (const char *) |
static __inline const PObject * | PTraceObjectInstance (const PObject *obj) |
static Comparison | InternalCompareObjectMemoryDirect (const PObject *obj1, const PObject *obj2, PINDEX size) |
Internal function caled from CompareObjectMemoryDirect() More... | |
![]() | |
PObject () | |
Constructor for PObject, made protected so cannot ever create one on its own. More... | |
![]() | |
unsigned | m_traceContextIdentifier |
![]() |
This class defines a thread-safe object in a collection.
This is part of a set of classes to solve the general problem of a collection (eg a PList or PDictionary) of objects that needs to be a made thread safe. Any thread can add, read, write or remove an object with both the object and the database of objects itself kept thread safe.
The act of adding a new object is simple and only requires locking the collection itself during the add.
Locating an object is more complicated. The obvious lock on the collection is made for the initial search. But we wish to have the full collection lock for as short a period as possible (for performance reasons) so we lock the individual object and release the lock on the collection.
A simple mutex on the object however is very dangerous as it can be (and should be able to be!) locked from other threads independently of the collection. If one of these threads subsequently needs to get at the collection (eg it wants to remove the object) then we will have a deadlock. Also, to avoid a race condition with the object begin deleted, the objects lock must be made while the collection lock is set. The performance gains are then lost as if something has the object locked for a long time, then another object wanting that object will actually lock the collection for a long time as well.
So, an object has 4 states: unused, referenced, reading & writing. With the additional rider of "being removed". This flag prevents new locks from being acquired and waits for all locks to be relinquished before removing the object from the system. This prevents numerous race conditions and accesses to deleted objects.
The "unused" state indicates the object exists in the collection but no threads anywhere is using it. It may be moved to any state by any thread while in this state. An object cannot be deleted (ie memory deallocated) until it is unused.
The "referenced" state indicates that a thread has a reference (eg pointer) to the object and it should not be deleted. It may be locked for reading or writing at any time thereafter.
The "reading" state is a form of lock that indicates that a thread is reading from the object but not writing. Multiple threads can obtain a read lock. Note the read lock has an implicit "reference" state in it.
The "writing" state is a form of lock where the data in the object may be changed. It can only be obtained exclusively and if there are no read locks present. Again there is an implicit reference state in this lock.
Note that threads going to the "referenced" state may do so regardless of the read or write locks present.
Access to safe objects (especially when in a safe collection) is recommended to by the PSafePtr<> class which will manage reference counting and the automatic unlocking of objects ones the pointer goes out of scope. It may also be used to lock each object of a collection in turn.
The enumeration of a PSafeCollection of PSafeObjects utilises the PSafePtr class in a classic "for loop" manner.
for (PSafePtr<MyClass> iter(collection, PSafeReadWrite); iter != NULL; ++iter) iter->Process();
There is one piece if important behaviour in the above. If while enumerating a specic object in the collection, that object is "safely deleted", you are guaranteed that the object is still usable and has not been phsyically deleted, however it will no longer be in the collection, so the enumeration will stop as it can no longer determine where in the collection it was.
What to do in this case is to take a "snapshot" at a point of time that can be safely and completely iterated over:
PSafeList<MyClass> collCopy = collection; for (PSafePtr<MyClass> iter(callCopy, PSafeReadWrite); iter != NULL; ++iter) iter->Process();
PSafeObject::PSafeObject | ( | PSafeObject * | indirectLock = NULL | ) |
Create a thread safe object.
indirectLock | Other safe object to be locked when this is locked |
|
virtual |
Do any garbage collection that may be required by the object so that it may be finally deleted.
This is especially useful if there a references back to this object which this object is in charge of disposing of. This reference "glare" is to be resolved by this function being called every time the owner collection is cleaning up, causing a cascade of clean ups that might need to be required.
Default implementation simply returns true.
|
inline |
Get count of references to this object.
Note this returns the value outside of any mutexes, so it could change at any moment. Care must be exercised in its use.
PBoolean PSafeObject::LockReadOnly | ( | ) | const |
Lock the object for Read Only access.
This will lock the object in read only mode. Multiple threads may lock the object read only, but only one thread can lock for read/write. Also, no read only threads can be present for the read/write lock to occur and no read/write lock can be present for any read only locks to occur.
If the function returns false, then the object has been flagged for deletion and the calling thread should immediately cease use of the object, possibly executing the SafeDereference() function to remove any references it may have acquired.
It is expected that the caller had already called the SafeReference() function (directly or implicitly) before calling this function. It is recommended that the PSafePtr<> class is used to automatically manage the reference counting and locking of objects.
PBoolean PSafeObject::LockReadWrite | ( | ) |
Lock the object for Read/Write access.
This will lock the object in read/write mode. Multiple threads may lock the object read only, but only one thread can lock for read/write. Also no read only threads can be present for the read/write lock to occur and no read/write lock can be present for any read only locks to occur.
If the function returns false, then the object has been flagged for deletion and the calling thread should immediately cease use of the object, possibly executing the SafeDereference() function to remove any references it may have acquired.
It is expected that the caller had already called the SafeReference() function (directly or implicitly) before calling this function. It is recommended that the PSafePtr<> class is used to automatically manage the reference counting and locking of objects.
PBoolean PSafeObject::SafeDereference | ( | ) |
Decrement the reference count for object.
This indicates that the thread no longer has anything to do with the object and it may be deleted (ie memory deallocated).
It is recommended that the PSafePtr<> class is used to manage this rather than the application calling this function directly.
PBoolean PSafeObject::SafelyCanBeDeleted | ( | ) | const |
Determine if the object can be safely deleted.
This determines if the object has been flagged for deletion and all references to it have been released.
This is typically used by the PSafeCollection class and is not expected to be used directly by an application.
PBoolean PSafeObject::SafeReference | ( | ) |
Increment the reference count for object.
This will guarantee that the object is not deleted (ie memory deallocated) as the caller thread is using the object, but not necessarily at this time locking it.
If the function returns false, then the object has been flagged for deletion and the calling thread should immediately cease using the object.
A typical use of this would be when an entity (eg a thread) has a pointer to the object but is not currenty accessing the objects data. The LockXXX functions may be called independetly of the reference system and the pointer beiong used for the LockXXX call is guaranteed to be usable.
It is recommended that the PSafePtr<> class is used to manage this rather than the application calling this function directly.
void PSafeObject::SafeRemove | ( | ) |
Set the removed flag.
This flags the object as beeing removed but does not physically delete the memory being used by it. The SafelyCanBeDeleted() can then be used to determine when all references to the object have been released so it may be safely deleted.
This is typically used by the PSafeCollection class and is not expected to be used directly by an application.
void PSafeObject::UnlockReadOnly | ( | ) | const |
Release the read only lock on an object.
Unlock the read only mutex that a thread had obtained. Multiple threads may lock the object read only, but only one thread can lock for read/write. Also, no read only threads can be present for the read/write lock to occur and no read/write lock can be present for any read only locks to occur.
It is recommended that the PSafePtr<> class is used to automatically manage the reference counting and unlocking of objects.
void PSafeObject::UnlockReadWrite | ( | ) |
Release the read/write lock on an object.
Unlock the read/write mutex that a thread had obtained. Multiple threads may lock the object read only, but only one thread can lock for read/write. Also, no read only threads can be present for the read/write lock to occur and no read/write lock can be present for any read only locks to occur.
It is recommended that the PSafePtr<> class is used to automatically manage the reference counting and unlocking of objects.