Merge branch 'master' of git.lumiera.org:/git/LUMIERA into gui

This commit is contained in:
Joel Holdsworth 2009-01-21 18:21:08 +00:00
commit cb13f5f74c
3 changed files with 42 additions and 25 deletions

View file

@ -89,7 +89,7 @@ class LumieraEnvironment(Environment):
#### temporary pre 1.0 SCons compatibility hack ####
_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:
ConfigBase = SCons.SConf.SConf
else:

View file

@ -41,22 +41,22 @@
namespace lib {
namespace { // implementation details
namespace nifty { // implementation details
template<class X>
struct NiftyHolder
struct Holder
{
static uint accessed_;
static char content_[sizeof(X)];
NiftyHolder()
Holder()
{
if (!accessed_)
new(content_) X();
++accessed_;
}
~NiftyHolder()
~Holder()
{
--accessed_;
if (0==accessed_)
@ -73,12 +73,12 @@ namespace lib {
};
template<class X>
uint NiftyHolder<X>::accessed_;
uint Holder<X>::accessed_;
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.
* 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 NiftyHolder<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 NiftyHolder<Monitor>::accessed_; }
uint use_count() { return nifty::Holder<PerClassMonitor>::accessed_; }
};

View file

@ -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");