アットウィキロゴ

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