Commit 48af56f9 authored by Pavel Vainerman's avatar Pavel Vainerman

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

parent 5061c023
...@@ -27,18 +27,17 @@ ...@@ -27,18 +27,17 @@
#include <string> #include <string>
#include <omnithread.h> #include <omnithread.h>
#include <signal.h> #include <signal.h>
#include <cc++/thread.h>
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
namespace UniSetTypes namespace UniSetTypes
{ {
typedef volatile sig_atomic_t mutex_atomic_t; typedef ost::AtomicCounter 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() лучше не пользоваться.
* Как пользоваться см. \ref MutexHowToPage * Как пользоваться см. \ref MutexHowToPage
* \todo Проверить правильность конструкторов копирования и operator= * \todo Проверить правильность конструкторов копирования и operator=
*/ */
class uniset_mutex class uniset_mutex
{ {
...@@ -51,10 +50,7 @@ namespace UniSetTypes ...@@ -51,10 +50,7 @@ namespace UniSetTypes
void lock(); void lock();
void unlock(); void unlock();
inline std::string name() inline std::string name(){ return nm; }
{
return nm;
};
protected: protected:
...@@ -93,6 +89,7 @@ namespace UniSetTypes ...@@ -93,6 +89,7 @@ namespace UniSetTypes
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Mutex c приоритетом WRlock над RLock...
class uniset_spin_mutex class uniset_spin_mutex
{ {
public: public:
...@@ -102,25 +99,57 @@ namespace UniSetTypes ...@@ -102,25 +99,57 @@ namespace UniSetTypes
void lock( int check_pause_msec=1 ); void lock( int check_pause_msec=1 );
void unlock(); void unlock();
void wrlock( int check_pause_msec=1 );
void rlock( int check_pause_msec=1 );
uniset_spin_mutex (const uniset_spin_mutex& r); uniset_spin_mutex (const uniset_spin_mutex& r);
const uniset_spin_mutex &operator=(const uniset_spin_mutex& r); const uniset_spin_mutex &operator=(const uniset_spin_mutex& r);
private: private:
friend class uniset_spin_lock; friend class uniset_spin_lock;
mutex_atomic_t m; ost::ThreadLock m;
ost::AtomicCounter wr_wait;
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
class uniset_spin_lock class uniset_spin_lock
{ {
public: 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(); ~uniset_spin_lock();
protected:
uniset_spin_lock( uniset_spin_mutex& _m ): m(_m){}
uniset_spin_mutex& m;
private: private:
uniset_spin_lock(const uniset_spin_lock&); uniset_spin_lock(const uniset_spin_lock&);
uniset_spin_lock& operator=(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 } // end of UniSetTypes namespace
......
...@@ -31,62 +31,57 @@ ...@@ -31,62 +31,57 @@
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); }
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(): uniset_mutex::uniset_mutex():
cnd(0), cnd(0),
nm("") nm(""),
locked(0)
{ {
mutex_atomic_set(&locked,0);
cnd = new omni_condition(&mtx); cnd = new omni_condition(&mtx);
} }
// -----------------------------------------------------------------------------
uniset_mutex::uniset_mutex( string name ): uniset_mutex::uniset_mutex( string name ):
nm(name) cnd(0),
nm(name),
locked(0)
{ {
mutex_atomic_set(&locked,0);
cnd = new omni_condition(&mtx); cnd = new omni_condition(&mtx);
} }
// -----------------------------------------------------------------------------
uniset_mutex::~uniset_mutex() uniset_mutex::~uniset_mutex()
{ {
unlock();
mutex_atomic_set(&locked,0);
delete cnd; delete cnd;
} }
// -----------------------------------------------------------------------------
void uniset_mutex::lock() void uniset_mutex::lock()
{ {
sem.wait(); sem.wait();
mutex_atomic_set(&locked,1); locked = 1;
} }
// -----------------------------------------------------------------------------
void uniset_mutex::unlock() void uniset_mutex::unlock()
{ {
mutex_atomic_set(&locked,0); locked = 0;
sem.post(); sem.post();
cnd->signal(); cnd->signal();
} }
// -----------------------------------------------------------------------------
bool uniset_mutex::isRelease() bool uniset_mutex::isRelease()
{ {
return !(bool)mutex_atomic_read(&locked); return !locked;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
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; // locked = r.locked;
return *this; return *this;
} }
// -----------------------------------------------------------------------------
uniset_mutex::uniset_mutex( const uniset_mutex& r ): uniset_mutex::uniset_mutex( const uniset_mutex& r ):
cnd(0), cnd(0),
nm(r.nm) nm(r.nm),
locked(r.locked)
{ {
cnd = new omni_condition(&mtx); cnd = new omni_condition(&mtx);
} }
...@@ -98,7 +93,7 @@ uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ): ...@@ -98,7 +93,7 @@ uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ):
if( timeMS <= 0 || mutex->isRelease() ) if( timeMS <= 0 || mutex->isRelease() )
{ {
mutex->lock(); mutex->lock();
mutex_atomic_set(&mlock,1); mlock = 1;
return; return;
} }
...@@ -114,27 +109,26 @@ uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ): ...@@ -114,27 +109,26 @@ uniset_mutex_lock::uniset_mutex_lock( uniset_mutex& m, int timeMS ):
<< timeMS << " msec для " << mutex->name() << endl; << timeMS << " msec для " << mutex->name() << endl;
} }
mutex_atomic_set(&mlock,0); mlock = 0;
mutex->mtx.unlock(); mutex->mtx.unlock();
return; // ресурс не захватываем return; // ресурс не захватываем
} }
mutex_atomic_set(&mlock,1); mlock = 1;
mutex->lock(); mutex->lock();
mutex->mtx.unlock(); mutex->mtx.unlock();
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool uniset_mutex_lock::lock_ok() bool uniset_mutex_lock::lock_ok()
{ {
return (bool)mutex_atomic_read(&mlock); return mlock;
} }
uniset_mutex_lock::~uniset_mutex_lock() uniset_mutex_lock::~uniset_mutex_lock()
{ {
if( mutex_atomic_read(&mlock) ) if( mlock )
{ {
mutex_atomic_set(&mlock,0); mlock = 0;
mutex->unlock(); mutex->unlock();
} }
} }
...@@ -144,14 +138,13 @@ uniset_mutex_lock& uniset_mutex_lock::operator=(const uniset_mutex_lock &r) ...@@ -144,14 +138,13 @@ uniset_mutex_lock& uniset_mutex_lock::operator=(const uniset_mutex_lock &r)
return *this; return *this;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
uniset_spin_mutex::uniset_spin_mutex() uniset_spin_mutex::uniset_spin_mutex():
wr_wait(0)
{ {
unlock();
} }
uniset_spin_mutex::~uniset_spin_mutex() uniset_spin_mutex::~uniset_spin_mutex()
{ {
unlock();
} }
const uniset_spin_mutex &uniset_spin_mutex::operator=( const uniset_spin_mutex& r ) 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& ...@@ -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 ) uniset_spin_mutex::uniset_spin_mutex( const uniset_spin_mutex& r )
{ {
unlock(); //unlock();
} }
void uniset_spin_mutex::lock( int check_pause_msec ) 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 ) if( check_pause_msec > 0 )
msleep(check_pause_msec); msleep(check_pause_msec);
} }
mutex_atomic_set(&m,1);
} }
void uniset_spin_mutex::unlock() 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 ): uniset_spin_lock::uniset_spin_lock( uniset_spin_mutex& _m, int check_pause_msec ):
m(_m) m(_m)
{ {
m.lock(check_pause_msec); m.lock(check_pause_msec);
} }
...@@ -193,19 +208,56 @@ uniset_spin_lock::~uniset_spin_lock() ...@@ -193,19 +208,56 @@ uniset_spin_lock::~uniset_spin_lock()
m.unlock(); m.unlock();
} }
uniset_spin_lock::uniset_spin_lock( const uniset_spin_lock& r ): uniset_spin_wrlock::uniset_spin_wrlock( uniset_spin_mutex& _m, int check_pause_msec ):
m(r.m) 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 ) if( this != &r )
m = r.m; m = r.m;
return *this; 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 #undef MUTEX_LOCK_SLEEP_MS
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <vector>
#include "Mutex.h" #include "Mutex.h"
#include "ThreadCreator.h" #include "ThreadCreator.h"
#include "UniSetTypes.h" #include "UniSetTypes.h"
...@@ -8,11 +9,12 @@ using namespace std; ...@@ -8,11 +9,12 @@ using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
uniset_mutex m; uniset_mutex m;
uniset_spin_mutex m_spin;
class MyClass class MyClass
{ {
public: public:
MyClass( const std::string& name ): nm(name) MyClass( const std::string& name ): nm(name),count(0)
{ {
thr = new ThreadCreator<MyClass>(this, &MyClass::thread); thr = new ThreadCreator<MyClass>(this, &MyClass::thread);
} }
...@@ -26,6 +28,13 @@ class MyClass ...@@ -26,6 +28,13 @@ class MyClass
{ {
thr->start(); 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: protected:
std::string nm; std::string nm;
...@@ -35,10 +44,9 @@ class MyClass ...@@ -35,10 +44,9 @@ class MyClass
while(1) while(1)
{ {
{ {
cerr << nm << ": before release=" << m.isRelease() << endl;
uniset_mutex_lock l(m); uniset_mutex_lock l(m);
count++;
msleep(30); msleep(30);
cerr << nm << ": after release=" << m.isRelease() << endl;
} }
msleep(10); msleep(10);
} }
...@@ -46,25 +54,263 @@ class MyClass ...@@ -46,25 +54,263 @@ class MyClass
private: private:
ThreadCreator<MyClass>* thr; 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 ) 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; int max = 10;
if( argc > 1 ) if( argc > 1 )
max = UniSetTypes::uni_atoi(argv[1]); max = UniSetTypes::uni_atoi(argv[1]);
#if 1
typedef std::vector<MyClass*> TVec;
TVec tvec(max);
for( int i=0; i<max; i++ ) for( int i=0; i<max; i++ )
{ {
ostringstream s; ostringstream s;
s << "t" << i; s << "t" << i;
MyClass* t = new MyClass(s.str()); MyClass* t = new MyClass(s.str());
tvec[i] = t;
t->execute(); t->execute();
msleep(50); 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; 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