Commit 3b35d826 authored by Pavel Vainerman's avatar Pavel Vainerman

(Thread): Переделал spin_mutex-ы на R и WR mutex-ы..

parent 1ccb0aa5
......@@ -27,18 +27,17 @@
#include <string>
#include <omnithread.h>
#include <signal.h>
#include <cc++/thread.h>
// -----------------------------------------------------------------------------------------
namespace UniSetTypes
{
typedef volatile sig_atomic_t mutex_atomic_t;
// typedef _Atomic_word mutex_atomic_t;
typedef ost::AtomicCounter mutex_atomic_t;
/*! \class uniset_mutex
* \note Напрямую функциями \a lock() и \a unlock() лучше не пользоваться.
* Как пользоваться см. \ref MutexHowToPage
* \todo Проверить правильность конструкторов копирования и operator=
* \todo Проверить правильность конструкторов копирования и operator=
*/
class uniset_mutex
{
......@@ -51,10 +50,7 @@ namespace UniSetTypes
void lock();
void unlock();
inline std::string name()
{
return nm;
};
inline std::string name(){ return nm; }
protected:
......@@ -93,6 +89,7 @@ namespace UniSetTypes
};
// -------------------------------------------------------------------------
// Mutex c приоритетом WRlock над RLock...
class uniset_spin_mutex
{
public:
......@@ -102,25 +99,57 @@ namespace UniSetTypes
void lock( int check_pause_msec=1 );
void unlock();
void wrlock( int check_pause_msec=1 );
void rlock( int check_pause_msec=1 );
uniset_spin_mutex (const uniset_spin_mutex& r);
const uniset_spin_mutex &operator=(const uniset_spin_mutex& r);
private:
friend class uniset_spin_lock;
mutex_atomic_t m;
ost::ThreadLock m;
ost::AtomicCounter wr_wait;
};
// -------------------------------------------------------------------------
class uniset_spin_lock
{
public:
uniset_spin_lock( uniset_spin_mutex& m, int check_pause_msec=1 );
uniset_spin_lock( uniset_spin_mutex& m, int check_pause_msec );
~uniset_spin_lock();
protected:
uniset_spin_lock( uniset_spin_mutex& _m ): m(_m){}
uniset_spin_mutex& m;
private:
uniset_spin_lock(const uniset_spin_lock&);
uniset_spin_lock& operator=(const uniset_spin_lock&);
uniset_spin_mutex& m;
};
class uniset_spin_wrlock:
protected uniset_spin_lock
{
public:
uniset_spin_wrlock( uniset_spin_mutex& m, int check_pause_msec=1 );
~uniset_spin_wrlock();
private:
uniset_spin_wrlock(const uniset_spin_wrlock&);
uniset_spin_wrlock& operator=(const uniset_spin_wrlock&);
};
class uniset_spin_rlock:
protected uniset_spin_lock
{
public:
uniset_spin_rlock( uniset_spin_mutex& m, int check_pause_msec=5 );
~uniset_spin_rlock();
private:
uniset_spin_rlock(const uniset_spin_rlock&);
uniset_spin_rlock& operator=(const uniset_spin_rlock&);
};
// -------------------------------------------------------------------------
} // end of UniSetTypes namespace
......
......@@ -31,62 +31,57 @@
using namespace std;
using namespace UniSetTypes;
// -----------------------------------------------------------------------------
static mutex_atomic_t mutex_atomic_read( mutex_atomic_t* m ){ return (*m); }
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)--; }
// -----------------------------------------------------------------------------
uniset_mutex::uniset_mutex():
cnd(0),
nm("")
nm(""),
locked(0)
{
mutex_atomic_set(&locked,0);
cnd = new omni_condition(&mtx);
}
// -----------------------------------------------------------------------------
uniset_mutex::uniset_mutex( string name ):
nm(name)
cnd(0),
nm(name),
locked(0)
{
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);
locked = 1;
}
// -----------------------------------------------------------------------------
void uniset_mutex::unlock()
{
mutex_atomic_set(&locked,0);
locked = 0;
sem.post();
cnd->signal();
}
// -----------------------------------------------------------------------------
bool uniset_mutex::isRelease()
{
return !(bool)mutex_atomic_read(&locked);
return !locked;
}
// -----------------------------------------------------------------------------
const uniset_mutex &uniset_mutex::operator=(const uniset_mutex& r)
{
if( this != &r )
locked = r.locked;
// if( this != &r )
// locked = r.locked;
return *this;
}
// -----------------------------------------------------------------------------
uniset_mutex::uniset_mutex( const uniset_mutex& r ):
cnd(0),
nm(r.nm)
nm(r.nm),
locked(r.locked)
{
cnd = new omni_condition(&mtx);
}
......@@ -98,7 +93,7 @@ uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ):
if( timeMS <= 0 || mutex->isRelease() )
{
mutex->lock();
mutex_atomic_set(&mlock,1);
mlock = 1;
return;
}
......@@ -114,27 +109,26 @@ uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ):
<< timeMS << " msec для " << mutex->name() << endl;
}
mutex_atomic_set(&mlock,0);
mlock = 0;
mutex->mtx.unlock();
return; // ресурс не захватываем
}
mutex_atomic_set(&mlock,1);
mlock = 1;
mutex->lock();
mutex->mtx.unlock();
}
// -----------------------------------------------------------------------------
bool uniset_mutex_lock::lock_ok()
{
return (bool)mutex_atomic_read(&mlock);
return mlock;
}
uniset_mutex_lock::~uniset_mutex_lock()
{
if( mutex_atomic_read(&mlock) )
if( mlock )
{
mutex_atomic_set(&mlock,0);
mlock = 0;
mutex->unlock();
}
}
......@@ -144,14 +138,13 @@ uniset_mutex_lock& uniset_mutex_lock::operator=(const uniset_mutex_lock &r)
return *this;
}
// -----------------------------------------------------------------------------
uniset_spin_mutex::uniset_spin_mutex()
uniset_spin_mutex::uniset_spin_mutex():
wr_wait(0)
{
unlock();
}
uniset_spin_mutex::~uniset_spin_mutex()
{
unlock();
}
const uniset_spin_mutex &uniset_spin_mutex::operator=( const uniset_spin_mutex& r )
......@@ -164,26 +157,48 @@ const uniset_spin_mutex &uniset_spin_mutex::operator=( const uniset_spin_mutex&
uniset_spin_mutex::uniset_spin_mutex( const uniset_spin_mutex& r )
{
unlock();
//unlock();
}
void uniset_spin_mutex::lock( int check_pause_msec )
{
while( mutex_atomic_read(&m) != 0 )
wr_wait += 1;
while( !m.tryWriteLock() )
{
if( check_pause_msec > 0 )
msleep(check_pause_msec);
}
wr_wait -= 1;
}
void uniset_spin_mutex::wrlock( int check_pause_msec )
{
wr_wait += 1;
while( !m.tryWriteLock() )
{
if( check_pause_msec > 0 )
msleep(check_pause_msec);
}
wr_wait -= 1;
}
void uniset_spin_mutex::rlock( int check_pause_msec )
{
while( wr_wait > 0 )
msleep(check_pause_msec);
while( !m.tryReadLock() )
{
if( check_pause_msec > 0 )
msleep(check_pause_msec);
}
mutex_atomic_set(&m,1);
}
void uniset_spin_mutex::unlock()
{
mutex_atomic_set(&m,0);
m.unlock();
}
// -------------------------------------------------------------------------------------------
uniset_spin_lock::uniset_spin_lock( uniset_spin_mutex& _m, int check_pause_msec ):
m(_m)
m(_m)
{
m.lock(check_pause_msec);
}
......@@ -193,19 +208,56 @@ uniset_spin_lock::~uniset_spin_lock()
m.unlock();
}
uniset_spin_lock::uniset_spin_lock( const uniset_spin_lock& r ):
m(r.m)
uniset_spin_wrlock::uniset_spin_wrlock( uniset_spin_mutex& _m, int check_pause_msec ):
uniset_spin_lock(_m)
{
m.wrlock(check_pause_msec);
}
uniset_spin_wrlock::~uniset_spin_wrlock()
{
// unlocked in uniset_spin_lock destructor
}
uniset_spin_wrlock::uniset_spin_wrlock( const uniset_spin_wrlock& r ):
uniset_spin_lock(r.m)
{
}
uniset_spin_lock& uniset_spin_lock::operator=(const uniset_spin_lock& r)
uniset_spin_wrlock& uniset_spin_wrlock::operator=(const uniset_spin_wrlock& r)
{
if( this != &r )
m = r.m;
return *this;
}
// -------------------------------------------------------------------------------------------
uniset_spin_rlock::uniset_spin_rlock( uniset_spin_mutex& _m, int check_pause_msec ):
uniset_spin_lock(_m)
{
m.rlock(check_pause_msec);
}
uniset_spin_rlock::~uniset_spin_rlock()
{
// unlocked in uniset_spin_lock destructor
}
uniset_spin_rlock::uniset_spin_rlock( const uniset_spin_rlock& r ):
uniset_spin_lock(r.m)
{
}
uniset_spin_rlock& uniset_spin_rlock::operator=(const uniset_spin_rlock& r)
{
if( this != &r )
m = r.m;
return *this;
}
// -----------------------------------------------------------------------------
#undef MUTEX_LOCK_SLEEP_MS
// -----------------------------------------------------------------------------
#include <string>
#include <sstream>
#include <vector>
#include "Mutex.h"
#include "ThreadCreator.h"
#include "UniSetTypes.h"
......@@ -8,11 +9,12 @@ using namespace std;
using namespace UniSetTypes;
uniset_mutex m;
uniset_spin_mutex m_spin;
class MyClass
{
public:
MyClass( const std::string& name ): nm(name)
MyClass( const std::string& name ): nm(name),count(0)
{
thr = new ThreadCreator<MyClass>(this, &MyClass::thread);
}
......@@ -26,6 +28,13 @@ class MyClass
{
thr->start();
}
inline std::string name(){ return nm; }
inline int lock_count(){ return count; }
// BAD CODE... only for test..
inline ThreadCreator<MyClass>* get(){ return thr; }
protected:
std::string nm;
......@@ -35,10 +44,9 @@ class MyClass
while(1)
{
{
cerr << nm << ": before release=" << m.isRelease() << endl;
uniset_mutex_lock l(m);
count++;
msleep(30);
cerr << nm << ": after release=" << m.isRelease() << endl;
}
msleep(10);
}
......@@ -46,25 +54,263 @@ class MyClass
private:
ThreadCreator<MyClass>* thr;
int count;
};
class MyClassSpin
{
public:
MyClassSpin( const std::string& name, bool rl=false ): nm(name),readLock(rl),count(0)
{
thr = new ThreadCreator<MyClassSpin>(this, &MyClassSpin::thread);
}
~MyClassSpin()
{
delete thr;
}
void execute()
{
thr->start();
}
inline std::string name(){ return nm; }
inline int lock_count(){ return count; }
protected:
std::string nm;
bool readLock;
void thread()
{
while(1)
{
if( !readLock )
{
// cerr << nm << ": before RWlock.." << endl;
uniset_spin_lock l(m_spin,5);
count++;
msleep(30);
// cerr << nm << ": after RWlock.." << endl;
}
else
{
// cerr << nm << "(readLock): before lock.." << endl;
uniset_spin_rlock l(m_spin);
count++;
msleep(20);
// cerr << nm << "(readLock): after lock.." << endl;
}
msleep(20);
}
}
private:
ThreadCreator<MyClassSpin>* thr;
int count;
};
bool check_wr_lock( ost::ThreadLock& m )
{
if( m.tryWriteLock() )
{
m.unlock();
return true;
}
return false;
}
bool check_r_lock( ost::ThreadLock& m )
{
if( m.tryReadLock() )
{
m.unlock();
return true;
}
return false;
}
int main( int argc, const char **argv )
{
try
{
#if 0
ost::ThreadLock m;
// cout << "test unlock.." << endl;
// m.unlock();
cout << "read lock.." << endl;
m.readLock();
cerr << "test write lock: " << (check_wr_lock(m) ? "FAIL" : "OK [0]") << endl;
cerr << "test read lock: " << (check_r_lock(m) ? "OK [1]" : "FAIL") << endl;
cout << "unlock.." << endl;
m.unlock();
cerr << "test write lock: " << (check_wr_lock(m) ? "OK [1]" : "FAIL") << endl;
cerr << "test read lock: " << (check_r_lock(m) ? "OK [1]" : "FAIL") << endl;
cout << "write lock.." << endl;
m.writeLock();
cerr << "test write lock: " << (check_wr_lock(m) ? "FAIL" : "OK [0]") << endl;
cerr << "test read lock: " << (check_r_lock(m) ? "FAIL" : "OK [0]") << endl;
cerr << endl << "***** uniset_spin_mutex ***" << endl;
uniset_spin_mutex m1;
cout << "read lock.." << endl;
m1.rlock();
cerr << "test read lock: " << endl;
m1.rlock();
cerr << "test read lock: OK" << endl;
m1.unlock();
cerr << "test write lock.." << endl;
m1.wrlock();
return 0;
#endif
#if 0
uniset_mutex um;
cout << "lock.." << endl;
um.lock();
cerr << "test lock: " << ( !um.isRelease() ? "OK" : "FAIL") << endl;
um.unlock();
cerr << "test unlock: " << (um.isRelease() ? "OK" : "FAIL") << endl;
um.lock();
cerr << "test second lock: " << (!um.isRelease() ? "OK" : "FAIL") << endl;
/*
cerr << "test lock again.." << endl;
um.lock();
cerr << "test lock again FAIL" << endl;
*/
um.unlock();
cerr << "**** uniset_mutex_lock..." << endl;
{
uniset_mutex_lock l(um);
cerr << "test lock: " << ( !um.isRelease() ? "OK" : "FAIL") << endl;
}
cerr << "test unlock: " << (um.isRelease() ? "OK" : "FAIL") << endl;
{
uniset_mutex_lock l(um);
cerr << "test second lock: " << (!um.isRelease() ? "OK" : "FAIL") << endl;
uniset_mutex_lock l2(um,500);
cerr << "test wait lock: " << ( !l2.lock_ok() ? "OK" : "FAIL") << endl;
}
uniset_mutex_lock l3(um,500);
cerr << "test wait lock: " << ( l3.lock_ok() ? "OK" : "FAIL") << endl;
return 0;
#endif
int max = 10;
if( argc > 1 )
max = UniSetTypes::uni_atoi(argv[1]);
#if 1
typedef std::vector<MyClass*> TVec;
TVec tvec(max);
for( int i=0; i<max; i++ )
{
ostringstream s;
s << "t" << i;
MyClass* t = new MyClass(s.str());
tvec[i] = t;
t->execute();
msleep(50);
}
pause();
cout << "TEST LOCK wait 10 sec.. (" << tvec.size() << " threads)" << endl;
msleep(10000);
cout << "TEST LOCK RESULT: " << endl;
for( TVec::iterator it=tvec.begin(); it!=tvec.end(); it++ )
{
int c = (*it)->lock_count();
(*it)->get()->stop();
cout << (*it)->name() << ": locked counter: " << c << " " << ( c!=0 ? "OK":"FAIL" ) << endl;
}
#endif
#if 0
typedef std::vector<MyClassSpin*> TSpinVec;
TSpinVec tsvec(max);
for( int i=0; i<max; i++ )
{
ostringstream s;
s << "t" << i;
MyClassSpin* t = new MyClassSpin(s.str());
tsvec[i] = t;
t->execute();
msleep(50);
}
cout << "TEST WRLOCK wait 10 sec.. (" << tsvec.size() << " threads)" << endl;
msleep(10000);
cout << "TEST WRLOCK RESULT: " << endl;
for( TSpinVec::iterator it=tsvec.begin(); it!=tsvec.end(); it++ )
{
int c = (*it)->lock_count();
cout << (*it)->name() << ": locked counter: " << c << " " << ( c!=0 ? "OK":"FAIL" ) << endl;
}
#endif
#if 0
for( int i=0; i<max; i++ )
{
ostringstream s;
s << "t" << i;
MyClassSpin* t = new MyClassSpin(s.str(),true);
t->execute();
msleep(50);
}
while(1)
{
{
cerr << "(writeLock): ************* lock WAIT..." << endl;
uniset_spin_wrlock l(m_spin);
cerr << "(writeLock): ************* lock OK.." << endl;
}
msleep(15);
}
#endif
// pause();
}
catch(omniORB::fatalException& fe)
{
cerr << "поймали omniORB::fatalException:" << endl;
cerr << " file: " << fe.file() << endl;
cerr << " line: " << fe.line() << endl;
cerr << " mesg: " << fe.errmsg() << endl;
}
catch( std::exception& e )
{
cerr << "catch: " << e.what() << endl;
}
catch(...)
{
cerr << "catch(...)" << endl;
}
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