This is a generic class for managing the lifetime of objects allocated on freestore, with a thread safe reference count..
More...
template<class T, class Dealloc = StandardArrayDelete<T>>
class Cgu::SharedLockHandle< T, Dealloc >
This is a generic class for managing the lifetime of objects allocated on freestore, with a thread safe reference count..
- See also
- SharedHandle ScopedHandle SharedHandleError
-
StandardArrayDelete CFree GFree GerrorFree GSliceFree GSliceFreeSize GSliceDestroy
Class SharedLockHandle is a version of the SharedHandle class which includes synchronization so that it can handle objects accessed in multiple threads (although the word Lock is in the title, by default it uses glib atomic functions to access the reference count rather than a mutex, so the overhead should be very small). Note that only the reference count is protected, so this is thread safe in the sense in which a raw pointer is thread safe. A shared handle accessed in one thread referencing a particular object is thread safe as against another shared handle accessing the same object in a different thread. It is thus suitable for use in different standard C++ containers which exist in different threads but which contain shared objects by reference. But:
- If the referenced object is to be modified in one thread and read or modified in another thread an appropriate mutex for the referenced object is required (unless that referenced object does its own locking).
- If the same instance of shared handle is to be modified in one thread (by assigning to the handle so that it references a different object), and copied (assigned from or used as the argument of a copy constructor), accessed, destroyed or modified in another thread, a mutex for that instance of shared handle is required.
- Objects referenced by shared handles which are objects for which POSIX provides no guarantees (in the main, those which are not built-in types), such as strings and similar containers, may not support concurrent reads in different threads. That depends on the library implementation concerned. If that is the case, a mutex for the referenced object will also be required when reading any given instance of such an object in more than one thread by dereferencing any shared handles referencing it (and indeed, when not using shared handles at all).
As of version 1.0.2, SharedLockHandle objects can be instantiated for pointers to constant objects (such as SharedLockHandle<const char*>), provided the deleter functor will take such pointers. Prior to version 1.0.2, it could only manage pointers to non-const objects.
This library provides StandardArrayDelete, CFree, GFree, GerrorFree, GSliceFree, GSliceFreeSize and GSliceDestroy deleter functors, which can be used as the second template parameter of the SharedLockHandle class. StandardArrayDelete is the default.
As mentioned, by default glib atomic functions are used to provide thread-safe manipulation of the reference count. However, from version 1.2.0 the symbol CGU_SHARED_LOCK_HANDLE_USE_MUTEX can be defined so that the library uses mutexes instead, which might be useful for some debugging purposes. Note that if CGU_SHARED_LOCK_HANDLE_USE_MUTEX is to be defined, this is best done by textually amending the shared_handle.h header file before the library is compiled. This will ensure that everything in the program and the library which includes the shared_handle.h header is guaranteed to see the same definitions so that the C++ standard's one-definition-rule is complied with.
From version 1.2.12, the library provides ==, != and < comparison operators for SharedLockHandles, but only if the library is compiled with the --with-smart-ptr-comp option, or if the user code defines the symbol CGU_USE_SMART_PTR_COMPARISON before shared_handle.h is first parsed. This is because, if user code has provided such operators for these smart pointers itself, a duplicated function definition would arise.
If the library is compiled with the --with-glib-memory-slices-no-compat configuration option, Cgu::SharedLockHandle constructs its reference counting internals using glib memory slices. Although it is safe in a multi-threaded program if glib < 2.32 is installed to construct a static SharedLockHandle object in global namespace (that is, prior to g_thread_init() being called) by means of the default constructor and/or a pointer argument of NULL, it is not safe if constructed with a non-NULL pointer value. If glib >= 2.32 is installed, global objects with memory slices are safe in all circumstances. (Having said that, it would be highly unusual to have global SharedLockHandle objects.)