templateで自動lock/unlockのてすと
解説
コンストラクタ/デストラクタをつかって、mutexなど同期プリミティブのlock/unlockをブロックの突入/脱出で自動的にやってみるテスト。
MFCにも似たようなのがあったが、method が仮想化されていて組み込みにはruntimeコストが機能のわりにはちょっと大げさな気がする。継承+仮想関数に代えてtemplate使えば、同期プリミティブをmutexやsemaphore, spinlockと色々選択できて、なおかつbuildtimeに解決しているのでruntimeコストは大げさにならない。 inline展開を期待して、普通にpthread_mutex_lock(),pthread_mutex_unlock()を使うのと変わらんだろ。 (と思う)
コード
#include <pthread.h>
template<typename lock_type>
class auto_lock {
public:
auto_lock(lock_type* lockref)
: _lockref(lockref) { _lockref->lock(); }
~auto_lock()
{ _lockref->unlock(); }
private:
lock_type* _lockref;
auto_lock();
auto_lock(const auto_lock&);
auto_lock& operator=(const auto_lock&);
bool operator==(const auto_lock&);
};
class mutex
{
public:
mutex()
{ posix_mutex = PTHREAD_MUTEX_INITIALIZER; }
~mutex()
{ pthread_mutex_destroy(&posix_mutex); }
void lock()
{ pthread_mutex_lock(&posix_mutex); }
void unlock()
{ pthread_mutex_unlock(&posix_mutex); }
private:
pthread_mutex_t posix_mutex;
mutex(const mutex&);
mutex& operator=(const mutex&);
bool operator==(const mutex&);
};
mutex my_mutex;
int thread_main()
{
{
auto_lock<mutex> m(&my_mutex);
// mymutexで排他制御されたブロック
}
return 0;
}
それでも、C++の醍醐味はやっぱ継承とポロモでしょ。ていう場合もあるかも。
class lockable
{
public:
virtual ~lockable() {}
virtual void lock() = 0;
virtual void unlock() = 0;
};
template<typename lock_type>
class virtual_lock
: public lockable
{
public:
virtual_lock() {}
~virtual_lock() {}
virtual void lock()
{_lockobj.lock();}
virtual void unlock()
{_lockobj.unlock();}
private:
lock_type _lockobj;
virtual_lock(const virtual_lock&);
virtual_lock& operator=(const virtual_lock&);
bool operator==(const virtual_lock&);
};
void hogehoge(lockable *lock)
{
auto_lock<lockable> l(lock);
// 省略
}
virtual_lock<mutex> my_virtual_mutex;
void hoge1()
{
hogehoge(&my_virtual_mutex);
}
すでにあるvirtual_lock<mutex>じゃないmutexはどうするの?てな場合むけ。
#include <assert.h>
template<typename lock_type>
class virtual_lock<lock_type*>
: public lockable
{
public:
virtual_lock()
: _lockref(NULL) {}
virtual_lock(lock_type *lock)
: _lockref(lock) {}
void assign(lock_type *lock)
{_lockref = lock;}
~virtual_lock() {}
virtual void lock()
{assert(_lockref != NULL); _lockref->lock();}
virtual void unlock()
{assert(_lockref != NULL); _lockref->unlock();}
private:
lock_type* _lockref;
virtual_lock(const virtual_lock&);
virtual_lock& operator=(const virtual_lock&);
bool operator==(const virtual_lock&);
};
void hoge2()
{
hogehoge(
&virtual_lock<mutex*>(&my_mutex)
);
}
最終更新:2007年02月22日 10:25