Merge branch 'master' of git.lumiera.org:/git/LUMIERA into gui
This commit is contained in:
commit
cb13f5f74c
3 changed files with 42 additions and 25 deletions
|
|
@ -89,7 +89,7 @@ class LumieraEnvironment(Environment):
|
||||||
|
|
||||||
#### temporary pre 1.0 SCons compatibility hack ####
|
#### temporary pre 1.0 SCons compatibility hack ####
|
||||||
_ver = map(int, SCons.__version__.split('.')[:2])
|
_ver = map(int, SCons.__version__.split('.')[:2])
|
||||||
_old = (_ver[0]<1 and _ver[1]<98)
|
_old = (_ver[0]<1 and _ver[1]<97)
|
||||||
if _old:
|
if _old:
|
||||||
ConfigBase = SCons.SConf.SConf
|
ConfigBase = SCons.SConf.SConf
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -41,22 +41,22 @@
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
|
|
||||||
namespace { // implementation details
|
namespace nifty { // implementation details
|
||||||
|
|
||||||
template<class X>
|
template<class X>
|
||||||
struct NiftyHolder
|
struct Holder
|
||||||
{
|
{
|
||||||
static uint accessed_;
|
static uint accessed_;
|
||||||
static char content_[sizeof(X)];
|
static char content_[sizeof(X)];
|
||||||
|
|
||||||
NiftyHolder()
|
Holder()
|
||||||
{
|
{
|
||||||
if (!accessed_)
|
if (!accessed_)
|
||||||
new(content_) X();
|
new(content_) X();
|
||||||
++accessed_;
|
++accessed_;
|
||||||
}
|
}
|
||||||
|
|
||||||
~NiftyHolder()
|
~Holder()
|
||||||
{
|
{
|
||||||
--accessed_;
|
--accessed_;
|
||||||
if (0==accessed_)
|
if (0==accessed_)
|
||||||
|
|
@ -73,12 +73,12 @@ namespace lib {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class X>
|
template<class X>
|
||||||
uint NiftyHolder<X>::accessed_;
|
uint Holder<X>::accessed_;
|
||||||
|
|
||||||
template<class X>
|
template<class X>
|
||||||
char NiftyHolder<X>::content_[sizeof(X)];
|
char Holder<X>::content_[sizeof(X)];
|
||||||
|
|
||||||
} // (End) implementation details
|
} // (End) nifty implementation details
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -87,27 +87,37 @@ namespace lib {
|
||||||
* to the parameter type as a whole, not an individual instance.
|
* to the parameter type as a whole, not an individual instance.
|
||||||
* After creating an instance, every other access specifying the same
|
* After creating an instance, every other access specifying the same
|
||||||
* type is blocked.
|
* 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
|
* @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
|
class ClassLock
|
||||||
: public Sync<CONF>::Lock
|
: public Sync<CONF>::Lock
|
||||||
{
|
{
|
||||||
typedef typename Sync<CONF>::Lock Lock;
|
typedef typename Sync<CONF>::Lock Lock;
|
||||||
typedef typename sync::Monitor<CONF> Monitor;
|
typedef typename sync::Monitor<CONF> Monitor;
|
||||||
|
|
||||||
|
struct PerClassMonitor : Monitor {};
|
||||||
|
|
||||||
Monitor&
|
Monitor&
|
||||||
getPerClassMonitor()
|
getPerClassMonitor()
|
||||||
{
|
{
|
||||||
static NiftyHolder<Monitor> __used_here;
|
static nifty::Holder<PerClassMonitor> __used_here;
|
||||||
|
ASSERT (1==use_count(), "static init broken");
|
||||||
|
|
||||||
return __used_here.get();
|
return __used_here.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ClassLock() : Lock (getPerClassMonitor()) {}
|
ClassLock() : Lock (getPerClassMonitor()) {}
|
||||||
|
|
||||||
uint use_count() { return NiftyHolder<Monitor>::accessed_; }
|
uint use_count() { return nifty::Holder<PerClassMonitor>::accessed_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,22 +34,25 @@ using test::Test;
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
namespace test {
|
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
|
const uint NUM_INSTANCES = 20; ///< number of probe instances to create
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* instances of this probe class will be created statically.
|
* Several instances of this probe class will be created.
|
||||||
* They utilise the class-based locking within ctor and dtor
|
* Each of them acquires the shared lock; but anyway, just
|
||||||
|
* by defining this class, the embedded Monitor got created.
|
||||||
*/
|
*/
|
||||||
struct Probe
|
struct Probe
|
||||||
{
|
{
|
||||||
Probe() { ClassLock<Probe> ctor_lock; }
|
ClassLock<Probe> shared_lock_;
|
||||||
~Probe() { ClassLock<Probe> dtor_lock; }
|
|
||||||
|
Probe() {}
|
||||||
|
~Probe() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // (End) test classes and data....
|
} // (End) test classes and data....
|
||||||
|
|
||||||
|
|
@ -76,17 +79,21 @@ namespace lib {
|
||||||
{
|
{
|
||||||
|
|
||||||
virtual void
|
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;
|
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... */
|
/** Register this test class... */
|
||||||
LAUNCHER (SyncClasslock_test, "unit common");
|
LAUNCHER (SyncClasslock_test, "unit common");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue