remove NoBug resourcetracker and switch back to plain pthreads

due to desing shortcomings, the resourcetracker
produces lots of false positives and inhibits
any further diagnostics regarding GUI startup.
This commit is contained in:
Fischlurch 2011-02-06 19:57:26 +01:00
parent ff0ae1527a
commit 29e67e828d
2 changed files with 147 additions and 142 deletions

72
src/lib/sync.cpp Normal file
View file

@ -0,0 +1,72 @@
/*
Sync - generic helper for object based locking and synchronisation
Copyright (C) Lumiera.org
2011, Hermann Vosseler <Ichthyostega@web.de>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* *****************************************************/
/** @file sync.cpp
** This compilation unit holds the static attribute struct
** for initialising pthread's recursive mutex.
**
*/
#include "lib/sync.hpp"
namespace lib {
namespace sync {
namespace { // private pthread attributes
pthread_mutexattr_t attribute_;
pthread_once_t is_init_ = PTHREAD_ONCE_INIT;
void
initAttribute()
{
pthread_mutexattr_init (&attribute_);
pthread_mutexattr_settype (&attribute_, PTHREAD_MUTEX_RECURSIVE);
}
inline pthread_mutexattr_t*
recursive_flag()
{
pthread_once (&is_init_, initAttribute);
return &attribute_;
}
}
/**
* @internal creating a recursive mutex.
* Defined here in a separate compilation unit,
* so it can refer to a single mutex attribute flag.
*/
Wrapped_RecursiveMutex::Wrapped_RecursiveMutex()
{
pthread_mutex_init (&mutex_, recursive_flag());
}
}}// lib::sync

View file

@ -23,10 +23,11 @@
/** @file sync.hpp
** Object Monitor based synchronisation.
** Actually, everything is implemented by delegating the raw locking/sync calls
** to the Lumiera backend. The purpose is to support and automate the most common
** use cases in a way which fits better with scoping and encapsulation; especially
** we build upon the monitor object pattern.
** The actual locking, signalling and waiting is implemented by delegating to the
** raw pthreads locking/sync calls. Rather, the purpose of the Sync baseclass is
** to support locking based on the <b>object monitor pattern</b>. This pattern
** describes a way of dealing with synchronisation known to play well with
** scoping, encapsulation and responsibility for a single purpose.
**
** A class becomes \em lockable by inheriting from lib::Sync with the appropriate
** parametrisation. This causes any instance to inherit a monitor member (object),
@ -68,21 +69,15 @@
#include "lib/error.hpp"
#include "lib/util.hpp"
#include "lib/diagnostic-context.hpp"
extern "C" {
#include "lib/mutex.h"
#include "lib/recmutex.h"
#include "lib/condition.h"
#include "lib/reccondition.h"
#include "lib/lockerror.h"
}
#include <boost/noncopyable.hpp>
#include <pthread.h>
#include <cerrno>
#include <ctime>
using boost::noncopyable;
namespace lib {
@ -91,177 +86,116 @@ namespace lib {
namespace sync {
namespace { // implementation shortcuts...
inline DiagnosticContext&
_accessContext()
{
return DiagnosticContext::access();
}
}
/* ========== adaptation layer for accessing backend/system level code ============== */
/* ========== adaptation layer for accessing the backend code ============== */
struct Wrapped_LumieraExcMutex
struct Wrapped_ExclusiveMutex
{
lumiera_mutex self_;
pthread_mutex_t mutex_;
protected:
Wrapped_LumieraExcMutex()
{ //TODO: currently passing no lineno/function info, put planning to use the DiagnosticContext to provide something in place of that later...
lumiera_mutex_init (&self_, "Obj.Monitor ExclMutex", &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
~Wrapped_LumieraExcMutex()
Wrapped_ExclusiveMutex()
{
lumiera_mutex_destroy (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT);
pthread_mutex_init (&mutex_, NULL);
}
~Wrapped_ExclusiveMutex()
{
if (pthread_mutex_destroy (&mutex_))
ERROR (sync, "Failure destroying mutex.");
} // shouldn't happen in a correct program
bool
void
lock()
{
return !!lumiera_mutex_lock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
if (pthread_mutex_lock (&mutex_))
throw lumiera::error::Fatal ("Mutex acquire failed");
} // shouldn't happen in a correct program
void
unlock()
{
lumiera_mutex_unlock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
if (pthread_mutex_unlock (&mutex_))
ERROR (sync, "Failure unlocking mutex.");
} // shouldn't happen in a correct program
};
struct Wrapped_LumieraRecMutex
struct Wrapped_RecursiveMutex
{
lumiera_recmutex self_;
pthread_mutex_t mutex_;
protected:
Wrapped_LumieraRecMutex()
Wrapped_RecursiveMutex();
~Wrapped_RecursiveMutex()
{
lumiera_recmutex_init (&self_, "Obj.Monitor RecMutex", &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
~Wrapped_LumieraRecMutex()
{
lumiera_recmutex_destroy (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT);
}
if (pthread_mutex_destroy (&mutex_))
ERROR (sync, "Failure destroying (rec)mutex.");
} // shouldn't happen in a correct program
bool
void
lock()
{
return !!lumiera_recmutex_lock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
if (pthread_mutex_lock (&mutex_))
throw lumiera::error::Fatal ("(rec)Mutex acquire failed");
} // shouldn't happen in a correct program
void
unlock()
{
lumiera_recmutex_unlock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
if (pthread_mutex_unlock (&mutex_))
ERROR (sync, "Failure unlocking (rec)mutex.");
} // shouldn't happen in a correct program
};
struct Wrapped_LumieraExcCond
template<class MTX>
struct Wrapped_Condition
: MTX
{
lumiera_condition self_;
pthread_cond_t cond_;
protected:
Wrapped_LumieraExcCond()
Wrapped_Condition()
{
lumiera_condition_init (&self_, "Obj.Monitor ExclCondition", &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
pthread_cond_init (&cond_, NULL);
}
~Wrapped_LumieraExcCond()
~Wrapped_Condition()
{
lumiera_condition_destroy (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT);
}
bool
lock()
{
return !!lumiera_condition_lock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
void
unlock()
{
lumiera_condition_unlock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
if (pthread_cond_destroy (&cond_))
ERROR (sync, "Failure destroying condition variable.");
} // shouldn't happen in a correct program
bool
wait()
{
return !!lumiera_condition_wait (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
int err;
do { err = pthread_cond_wait (&this->cond_, &this->mutex_);
} while(err == EINTR);
if (err) lumiera_lockerror_set (err, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
return !err;
}
bool
timedwait (const struct timespec* timeout)
{
return !!lumiera_condition_timedwait (&self_, timeout, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
int err;
do { err = pthread_cond_timedwait (&this->cond_, &this->mutex_, timeout);
} while(err == EINTR);
if (err) lumiera_lockerror_set (err, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
return !err;
}
void
signal()
{
lumiera_condition_signal (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
void
broadcast()
{
lumiera_condition_broadcast (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
void signal() { pthread_cond_signal (&cond_); }
void broadcast() { pthread_cond_broadcast (&cond_); }
};
struct Wrapped_LumieraRecCond
{
lumiera_reccondition self_;
protected:
Wrapped_LumieraRecCond()
{
lumiera_reccondition_init (&self_, "Obj.Monitor RecCondition", &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
~Wrapped_LumieraRecCond()
{
lumiera_reccondition_destroy (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT);
}
bool
lock()
{
return !!lumiera_reccondition_lock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
void
unlock ()
{
lumiera_reccondition_unlock (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
bool
wait()
{
return !!lumiera_reccondition_wait (&self_, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
bool
timedwait (const struct timespec* timeout)
{
return !!lumiera_reccondition_timedwait (&self_, timeout, &NOBUG_FLAG(sync), _accessContext(), NOBUG_CONTEXT_NOFUNC);
}
void
signal()
{
lumiera_reccondition_signal (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
void
broadcast()
{
lumiera_reccondition_broadcast (&self_, &NOBUG_FLAG(sync), NOBUG_CONTEXT_NOFUNC);
}
};
@ -296,20 +230,20 @@ namespace lib {
class Timeout;
template<class CDX>
template<class MTX>
class Condition
: public Mutex<CDX>
: public Mutex<Wrapped_Condition<MTX> >
{
typedef Mutex<CDX> _PM;
typedef Wrapped_Condition<MTX> Cond;
public:
void
signal (bool wakeAll=false)
{
if (wakeAll)
CDX::broadcast ();
Cond::broadcast ();
else
CDX::signal ();
Cond::signal ();
}
@ -320,12 +254,12 @@ namespace lib {
bool ok = true;
while (ok && !predicate())
if (waitEndTime)
ok = CDX::timedwait (&waitEndTime);
ok = Cond::timedwait (&waitEndTime);
else
ok = CDX::wait ();
ok = Cond::wait ();
if (!ok && lumiera_error_expect(LUMIERA_ERROR_LOCK_TIMEOUT)) return false;
lumiera::throwOnError(); // any other error thows
lumiera::throwOnError(); // any other error throws
return true;
}
@ -435,10 +369,10 @@ namespace lib {
bool isTimedWait() {return (timeout_);}
};
typedef Mutex<Wrapped_LumieraExcMutex> NonrecursiveLock_NoWait;
typedef Mutex<Wrapped_LumieraRecMutex> RecursiveLock_NoWait;
typedef Condition<Wrapped_LumieraExcCond> NonrecursiveLock_Waitable;
typedef Condition<Wrapped_LumieraRecCond> RecursiveLock_Waitable;
typedef Mutex<Wrapped_ExclusiveMutex> NonrecursiveLock_NoWait;
typedef Mutex<Wrapped_RecursiveMutex> RecursiveLock_NoWait;
typedef Condition<Wrapped_ExclusiveMutex> NonrecursiveLock_Waitable;
typedef Condition<Wrapped_RecursiveMutex> RecursiveLock_Waitable;
} // namespace sync (helpers and building blocks)
@ -488,7 +422,6 @@ namespace lib {
public:
class Lock
: DiagnosticContext
{
Monitor& mon_;