Commit 5a73a16c authored by Pavel Vainerman's avatar Pavel Vainerman

Mutex reingeniring

parent 3e6645e2
...@@ -34,10 +34,6 @@ ...@@ -34,10 +34,6 @@
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
namespace UniSetTypes namespace UniSetTypes
{ {
typedef sig_atomic_t mutex_atomic_t;
// typedef _Atomic_word mutex_atomic_t;
/*! \class uniset_mutex /*! \class uniset_mutex
* \note \a lock() \a unlock() . * \note \a lock() \a unlock() .
...@@ -48,10 +44,14 @@ namespace UniSetTypes ...@@ -48,10 +44,14 @@ namespace UniSetTypes
{ {
public: public:
uniset_mutex(); uniset_mutex();
uniset_mutex( std::string name ); uniset_mutex( const std::string name );
~uniset_mutex(); ~uniset_mutex();
bool isRelease(); inline bool isRelease() const
{
return (bool)release;
};
void lock(); void lock();
void unlock(); void unlock();
...@@ -66,18 +66,13 @@ namespace UniSetTypes ...@@ -66,18 +66,13 @@ namespace UniSetTypes
friend class uniset_mutex_lock; friend class uniset_mutex_lock;
uniset_mutex (const uniset_mutex& r); uniset_mutex (const uniset_mutex& r);
const uniset_mutex &operator=(const uniset_mutex& r); const uniset_mutex &operator=(const uniset_mutex& r);
omni_condition* cnd; volatile sig_atomic_t release;
std::string nm; const std::string nm;
omni_semaphore sem; omni_condition* ocond;
omni_mutex mtx; omni_mutex omutex;
mutex_atomic_t locked;
}; };
/*! \class uniset_mutex_lock /*! \class uniset_mutex_lock
* \author Pavel Vainerman
* \date $Date: 2007/11/18 19:13:35 $
* \version $Id: Mutex.h,v 1.14 2007/11/18 19:13:35 vpashka Exp $
*
* . . \ref MutexHowToPage * . . \ref MutexHowToPage
* \note , lock ... * \note , lock ...
* \warning ! * \warning !
...@@ -93,13 +88,13 @@ namespace UniSetTypes ...@@ -93,13 +88,13 @@ namespace UniSetTypes
private: private:
uniset_mutex* mutex; uniset_mutex* mutex;
mutex_atomic_t mlock;
uniset_mutex_lock(const uniset_mutex_lock&); uniset_mutex_lock(const uniset_mutex_lock&);
uniset_mutex_lock& operator=(const uniset_mutex_lock&); uniset_mutex_lock& operator=(const uniset_mutex_lock&);
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
class uniset_spin_mutex class uniset_spin_mutex:
public uniset_mutex
{ {
public: public:
uniset_spin_mutex(); uniset_spin_mutex();
...@@ -111,7 +106,6 @@ namespace UniSetTypes ...@@ -111,7 +106,6 @@ namespace UniSetTypes
void unlock(); void unlock();
private: private:
mutex_atomic_t m;
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
class uniset_spin_lock class uniset_spin_lock
......
...@@ -33,177 +33,97 @@ ...@@ -33,177 +33,97 @@
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static mutex_atomic_t mutex_atomic_read( mutex_atomic_t* m ){ return (*m); } #define MUTEX_LOCK_SLEEP_MS 20
static mutex_atomic_t mutex_atomic_set( mutex_atomic_t* m, int val ){ return (*m) = val; } // -------------------------------------------------------------------------------------------
//static void mutex_atomic_inc( mutex_atomic_t* m ){ (*m)++; }
//static void mutex_atomic_dec( mutex_atomic_t* m ){ (*m)--; }
// -----------------------------------------------------------------------------
#ifndef HAVE_LINUX_LIBC_HEADERS_INCLUDE_LINUX_FUTEX_H
uniset_mutex::uniset_mutex(): uniset_mutex::uniset_mutex():
cnd(0), release(1),
nm("") nm("")
{ {
mutex_atomic_set(&locked,0); ocond = new omni_condition(&omutex);
cnd = new omni_condition(&mtx);
}
uniset_mutex::uniset_mutex( string name ):
nm(name)
{
mutex_atomic_set(&locked,0);
cnd = new omni_condition(&mtx);
}
uniset_mutex::~uniset_mutex()
{
unlock();
mutex_atomic_set(&locked,0);
delete cnd;
}
void uniset_mutex::lock()
{
sem.wait();
mutex_atomic_set(&locked,1);
}
void uniset_mutex::unlock()
{
mutex_atomic_set(&locked,0);
sem.post();
cnd->signal();
}
bool uniset_mutex::isRelease()
{
return (bool)!mutex_atomic_read(&locked);
}
// -----------------------------------------------------------------------------
#else // HAVE_LINUX_FUTEX_H
// -----------------------------------------------------------------------------
// mutex futex
// http://kerneldump.110mb.com/dokuwiki/doku.php?id=wiki:futexes_are_tricky_p3
// : http://people.redhat.com/drepper/futex.pdf
uniset_mutex::uniset_mutex():
val(0),nm("")
{
} }
uniset_mutex::uiset_mutex( std::string name ) uniset_mutex::uniset_mutex( const string name ):
val(0), release(1),
nm(name) nm(name)
{ {
ocond = new omni_condition(&omutex);
} }
uniset_mutex::~uniset_mutex() uniset_mutex::~uniset_mutex()
{ {
unlock(); delete ocond;
} }
void uniset_mutex::lock() void uniset_mutex::lock()
{ {
int c; release = 0;
if( (c = cmpxchg(val, 0, 1))!= 0 ) omutex.lock();
{
do
{
if( c==2 || cmpxchg(val, 1, 2)!=0 )
futex_wait(&val, 2);
}
while( (c = cmpxchg(val, 0, 2))!=0 );
}
} }
void uniset_mutex::unlock() void uniset_mutex::unlock()
{ {
if( atomic_dec(val)!=1 ) omutex.unlock();
{ release = 1;
val = 0;
futex_wake(&val, 1);
}
}
bool uniset_mutex::isRelease()
{
return (bool)cmpxchg(val, 1, 2);
} }
// -----------------------------------------------------------------------------
#endif // HAVE_LINUX_FUTEX_H
// -----------------------------------------------------------------------------
const uniset_mutex &uniset_mutex::operator=(const uniset_mutex& r) const uniset_mutex &uniset_mutex::operator=(const uniset_mutex& r)
{ {
if( this != &r ) if( this != &r )
locked = r.locked; {
release = r.release;
if( release )
unlock();
else
lock();
}
return *this; return *this;
} }
uniset_mutex::uniset_mutex( const uniset_mutex& r ): uniset_mutex::uniset_mutex (const uniset_mutex& r):
cnd(0), release(r.release),
nm(r.nm) nm(r.nm)
{ {
cnd = new omni_condition(&mtx);
} }
// ----------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ): uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int t_msec ):
mutex(&m) mutex(&m)
{ {
if( timeMS <= 0 || mutex->isRelease() ) if( m.isRelease() )
{ {
mutex->lock(); m.lock();
mutex_atomic_set(&mlock,1); // cerr << "....locked.." << endl;
return; return;
} }
unsigned long sec, msec; if( t_msec > 0 )
omni_thread::get_time(&sec,&msec, timeMS/1000, (timeMS%1000)*1000000 );
mutex->mtx.lock();
if( !mutex->cnd->timedwait(sec, msec) )
{ {
if( !mutex->name().empty() && unideb.debugging( Debug::type(Debug::LEVEL9|Debug::WARN)) ) m.lock();
unsigned long sec, msec;
omni_thread::get_time(&sec,&msec,t_msec/1000,(t_msec%1000)*1000000);
// cerr << "....wait mutex msec=" << t_msec << endl;
// m.ocond->timedwait(sec, msec);
if( !m.ocond->timedwait(sec, msec) )
{ {
unideb[Debug::type(Debug::LEVEL9|Debug::WARN)] m.unlock();
<< "(mutex_lock): " return;
<< timeMS << " msec " << mutex->name() << endl;
} }
mutex_atomic_set(&mlock,0);
mutex->mtx.unlock();
return; //
} }
// m.lock();
mutex_atomic_set(&mlock,1);
mutex->lock();
mutex->mtx.unlock();
}
// -----------------------------------------------------------------------------
bool uniset_mutex_lock::lock_ok()
{
return (bool)mutex_atomic_read(&mlock);
} }
// -------------------------------------------------------------------------------------------
uniset_mutex_lock::~uniset_mutex_lock() uniset_mutex_lock::~uniset_mutex_lock()
{ {
if( mutex_atomic_read(&mlock) )
{
mutex_atomic_set(&mlock,0);
mutex->unlock(); mutex->unlock();
} mutex->ocond->signal();
} }
// ----------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
uniset_mutex_lock& uniset_mutex_lock::operator=(const uniset_mutex_lock &r) uniset_mutex_lock& uniset_mutex_lock::operator=(const uniset_mutex_lock &r)
{ {
return *this; return *this;
} }
// ----------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
#ifndef HAVE_LINUX_LIBC_HEADERS_INCLUDE_LINUX_FUTEX_H
uniset_spin_mutex::uniset_spin_mutex() uniset_spin_mutex::uniset_spin_mutex()
{ {
unlock(); unlock();
...@@ -229,54 +149,14 @@ uniset_spin_mutex::uniset_spin_mutex( const uniset_spin_mutex& r ) ...@@ -229,54 +149,14 @@ uniset_spin_mutex::uniset_spin_mutex( const uniset_spin_mutex& r )
void uniset_spin_mutex::lock( int check_pause_msec ) void uniset_spin_mutex::lock( int check_pause_msec )
{ {
while( mutex_atomic_read(&m) != 0 ) lock();
{
if( check_pause_msec > 0 )
msleep(check_pause_msec);
}
mutex_atomic_set(&m,1);
} }
void uniset_spin_mutex::unlock() void uniset_spin_mutex::unlock()
{ {
m = 0; unlock();
}
#else // HAVE_FUTEX
// mutex futex
// http://kerneldump.110mb.com/dokuwiki/doku.php?id=wiki:futexes_are_tricky_p3
// : http://people.redhat.com/drepper/futex.pdf
void uniset_spin_mutex::lock( int check_pause_msec )
{
struct timespec tm;
tm.tv_sec = check_pause_msec / 1000;
tm.tv_nsec = check_pause_msec%1000;
int c;
if( (c = cmpxchg(val, 0, 1))!= 0 )
{
do
{
if( c==2 || cmpxchg(val, 1, 2)!=0 )
{
if( futex_wait(&val, 2,tm) == ETIMEDOUT )
return;
}
}
while( (c = cmpxchg(val, 0, 2))!=0 );
}
} }
void uniset_spin_mutex::unlock()
{
if( atomic_dec(val)!=1 )
{
val = 0;
futex_wake(&val, 1);
}
}
#endif // HAVE_FUTEX
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
uniset_spin_lock::uniset_spin_lock( uniset_spin_mutex& _m, int check_pause_msec ): uniset_spin_lock::uniset_spin_lock( uniset_spin_mutex& _m, int check_pause_msec ):
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# This file is part of the UniSet library # # This file is part of the UniSet library #
############################################################################ ############################################################################
noinst_PROGRAMS = passivetimer unixml ui noinst_PROGRAMS = passivetimer unixml ui umutex
passivetimer_SOURCES = passivetimer.cc passivetimer_SOURCES = passivetimer.cc
passivetimer_LDADD = $(top_builddir)/lib/libUniSet.la passivetimer_LDADD = $(top_builddir)/lib/libUniSet.la
...@@ -16,6 +16,10 @@ ui_SOURCES = ui.cc ...@@ -16,6 +16,10 @@ ui_SOURCES = ui.cc
ui_LDADD = $(top_builddir)/lib/libUniSet.la ui_LDADD = $(top_builddir)/lib/libUniSet.la
ui_CPPFLAGS = -I$(top_builddir)/include ui_CPPFLAGS = -I$(top_builddir)/include
umutex_SOURCES = umutex.cc
umutex_LDADD = $(top_builddir)/lib/libUniSet.la
umutex_CPPFLAGS = -I$(top_builddir)/include
include $(top_builddir)/conf/setting.mk include $(top_builddir)/conf/setting.mk
#include <string>
#include "Mutex.h"
#include "ThreadCreator.h"
#include "UniSetTypes.h"
using namespace std;
using namespace UniSetTypes;
uniset_mutex m;
class MyClass
{
public:
MyClass( const std::string name ): nm(name)
{
thr = new ThreadCreator<MyClass>(this, &MyClass::thread);
}
~MyClass()
{
delete thr;
}
void execute()
{
thr->start();
}
protected:
std::string nm;
void thread()
{
while(1)
{
{
cerr << nm << ": before release=" << m.isRelease() << endl;
uniset_mutex_lock l(m,5000);
cerr << nm << ": after release=" << m.isRelease() << endl;
}
msleep(300);
}
}
private:
ThreadCreator<MyClass>* thr;
};
int main( int argc, const char **argv )
{
MyClass* mc1 = new MyClass("t1");
MyClass* mc2 = new MyClass("t2");
// m.lock();
mc1->execute();
msleep(200);
mc2->execute();
pause();
// m.unlock();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment