ATL::CComMultiThreadModelクラス(リンク先はMSDNライブラリ)の実装を見ていると、もう少し今時っぽい感じにしたいなと思いました。というわけで、さくっと書いてみました。

#define _ATL_NO_AUTOMATIC_NAMESPACE
 
#include <atlbase.h>
#include <atlcom.h>
#include <mutex>
 
class ComMultiThreadModelExNoCS
{
public:
  static ULONG WINAPI Increment(_Inout_ LPLONG p) throw()
  {
    return ::_InterlockedIncrement(p);
  }
  static ULONG WINAPI Decrement(_Inout_ LPLONG p) throw()
  {
    return ::_InterlockedDecrement(p);
  }
  typedef ATL::CComFakeCriticalSection AutoCriticalSection;
  typedef ATL::CComFakeCriticalSection AutoDeleteCriticalSection;
  typedef ATL::CComFakeCriticalSection CriticalSection;
  typedef ComMultiThreadModelExNoCS ThreadModelNoCS;
};
 
class RecursiveMutexForAtl
{
public:
  RecursiveMutexForAtl() {}
  ~RecursiveMutexForAtl() {}
 
  HRESULT Lock()
  {
    m_mutex.lock();
    return S_OK;
  }
  HRESULT Unlock()
  {
    m_mutex.unlock();
    return S_OK;
  }
 
  HRESULT Init() throw() { return S_OK; }
  HRESULT Term() throw() { return S_OK; }
 
  std::recursive_mutex m_mutex;
};
 
class ComMultiThreadModelEx
{
public:
  static ULONG WINAPI Increment(_Inout_ long* p) throw()
  {
    return ::_InterlockedIncrement(p);
  }
  static ULONG WINAPI Decrement(_Inout_ long* p) throw()
  {
    return ::_InterlockedDecrement(p);
  }
  typedef RecursiveMutexForAtl AutoCriticalSection;
  typedef RecursiveMutexForAtl AutoDeleteCriticalSection;
  typedef RecursiveMutexForAtl CriticalSection;
  typedef ComMultiThreadModelExNoCS ThreadModelNoCS;
};

特徴は2つです。

  • インクリメント・デクリメントをコンパイラ組み込み版にした。
  • クリティカルセクションの代わりに、std::recursive_mutexを採用してみた。

Windowsのクリティカルセクションは再入OKなので、それにあわせてrecursive_mutexを選びました。std::mutexやVC++のConcurrency Runtimeのcritical_sectionクラスなどもいいですね。あるいは、WindowsのCRITICAL_SECTIONを使うけど、InitializeCriticalSectionAndSpinCount関数を呼び出すようにして、スピンロックの値を指定するという改良も考えられます。

スポンサード リンク

この記事のカテゴリ

  • ⇒ マイATL::CComMultiThreadModelを作る
  • ⇒ マイATL::CComMultiThreadModelを作る