diff --git a/src/lib/sync-classlock.hpp b/src/lib/sync-classlock.hpp index ea2c1a75d..f4fe93dda 100644 --- a/src/lib/sync-classlock.hpp +++ b/src/lib/sync-classlock.hpp @@ -87,27 +87,37 @@ namespace lib { * to the parameter type as a whole, not an individual instance. * After creating an instance, every other access specifying the same * type is blocked. - * @warn beware of recursion when using a nonrecursive Mutex + * @note the Lock is recursive, because several instances within the same + * thread may want to acquire it at the same time without deadlock. + * @note there is a design sloppiness, as two instantiations of the + * ClassLock template with differing CONF count as different type. + * Actually using two different configurations within for a single + * class X should be detected and flagged as error, but actually + * just two non-shared lock instances get created silently. Beware! * @see Sync::Lock the usual simple instance-bound variant */ - template + template class ClassLock : public Sync::Lock { typedef typename Sync::Lock Lock; typedef typename sync::Monitor Monitor; + struct PerClassMonitor : Monitor {}; + Monitor& getPerClassMonitor() { - static nifty::Holder __used_here; + static nifty::Holder __used_here; + ASSERT (1==use_count(), "static init broken"); + return __used_here.get(); } public: ClassLock() : Lock (getPerClassMonitor()) {} - uint use_count() { return nifty::Holder::accessed_; } + uint use_count() { return nifty::Holder::accessed_; } }; diff --git a/tests/lib/sync-classlock-test.cpp b/tests/lib/sync-classlock-test.cpp index 81ad457d1..2cfa271e5 100644 --- a/tests/lib/sync-classlock-test.cpp +++ b/tests/lib/sync-classlock-test.cpp @@ -34,22 +34,25 @@ using test::Test; namespace lib { namespace test { - - namespace { // private test classes and data... + namespace { // private test classes and data... + const uint NUM_INSTANCES = 20; ///< number of probe instances to create - /** - * instances of this probe class will be created statically. - * They utilise the class-based locking within ctor and dtor + /** + * Several instances of this probe class will be created. + * Each of them acquires the shared lock; but anyway, just + * by defining this class, the embedded Monitor got created. */ struct Probe { - Probe() { ClassLock ctor_lock; } - ~Probe() { ClassLock dtor_lock; } + ClassLock shared_lock_; + + Probe() {} + ~Probe() {} }; - + } // (End) test classes and data.... @@ -76,17 +79,21 @@ namespace lib { { virtual void - run (Arg) + run (Arg) { - static Probe objs[NUM_INSTANCES]; + { + Probe objs[NUM_INSTANCES]; + + ASSERT (1 == objs[0].shared_lock_.use_count()); + } ClassLock get_class_lock; - ASSERT ( 1 == get_class_lock.use_count()); // ClassLock got created exactly once - } + ASSERT ( 1 == get_class_lock.use_count()); // embedded PerClassMonitor got created exactly once + } // and stays alive until static dtors are called.... }; - + /** Register this test class... */ LAUNCHER (SyncClasslock_test, "unit common");