Further ClassLock refactoring; added linkonce assertion check
This commit is contained in:
parent
801f070a7d
commit
974e83676a
2 changed files with 34 additions and 17 deletions
|
|
@ -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<class X, class CONF = NonrecursiveLock_NoWait>
|
||||
template<class X, class CONF = RecursiveLock_NoWait>
|
||||
class ClassLock
|
||||
: public Sync<CONF>::Lock
|
||||
{
|
||||
typedef typename Sync<CONF>::Lock Lock;
|
||||
typedef typename sync::Monitor<CONF> Monitor;
|
||||
|
||||
struct PerClassMonitor : Monitor {};
|
||||
|
||||
Monitor&
|
||||
getPerClassMonitor()
|
||||
{
|
||||
static nifty::Holder<Monitor> __used_here;
|
||||
static nifty::Holder<PerClassMonitor> __used_here;
|
||||
ASSERT (1==use_count(), "static init broken");
|
||||
|
||||
return __used_here.get();
|
||||
}
|
||||
|
||||
public:
|
||||
ClassLock() : Lock (getPerClassMonitor()) {}
|
||||
|
||||
uint use_count() { return nifty::Holder<Monitor>::accessed_; }
|
||||
uint use_count() { return nifty::Holder<PerClassMonitor>::accessed_; }
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Probe> ctor_lock; }
|
||||
~Probe() { ClassLock<Probe> dtor_lock; }
|
||||
ClassLock<Probe> 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<Probe> get_class_lock;
|
||||
ASSERT ( 1 == get_class_lock.use_count()); // ClassLock<Probe> got created exactly once
|
||||
}
|
||||
ASSERT ( 1 == get_class_lock.use_count()); // embedded PerClassMonitor<Probe> got created exactly once
|
||||
} // and stays alive until static dtors are called....
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** Register this test class... */
|
||||
LAUNCHER (SyncClasslock_test, "unit common");
|
||||
|
|
|
|||
Loading…
Reference in a new issue