InterlockedIncrement
、などのWin32組み込み関数をラップするラッパークラスを作成しようとしていますInterlockedExchange
。私の問題は、同様の組み込み関数をサポートする他のプラットフォームでもおそらく類似していますが。
私は基本的なテンプレートタイプを持っています:
template <typename T, size_t W = sizeof(T)>
class Interlocked {};
これは、異なるサイズのデータ型に部分的に特化しています。たとえば、32 ビットのものは次のとおりです。
//
// Partial specialization for 32 bit types
//
template<typename T>
class Interlocked <T, sizeof(__int32)>
{
public:
Interlocked<T, sizeof(__int32)>() {};
Interlocked<T, sizeof(__int32)>(T val) : m_val(val) {}
Interlocked<T, sizeof(__int32)>& Interlocked<T, sizeof(__int32)>::operator= (T val)
{
InterlockedExchange((LONG volatile *)&m_val, (LONG)val);
return *this;
}
Interlocked<T, sizeof(__int32)> Interlocked<T, sizeof(__int32)>::operator++()
{
return static_cast<T>(InterlockedIncrement((LONG volatile *)&m_val));
}
Interlocked<T, sizeof(__int32)> Interlocked<T, sizeof(__int32)>::operator--()
{
return static_cast<T>(InterlockedDecrement((LONG volatile *)&m_val));
}
Interlocked<T, sizeof(__int32)>& Interlocked<T, sizeof(__int32)>::operator+(T val)
{
InterlockedExchangeAdd((LONG volatile *)&m_val, (LONG) val);
return *this;
}
Interlocked<T, sizeof(__int32)>& Interlocked<T, sizeof(__int32)>::operator-(T val)
{
InterlockedExchangeSubtract((LONG volatile *)&m_val, (LONG) val);
return *this;
}
operator T()
{
return m_val;
}
private:
T m_val;
};
しかし、そのようなオブジェクトを安全に書く方法がわからないという結論に達しています。*this
具体的には、インターロック操作を実行した後に戻ると、変数が返される前に別のスレッドが変数を変更する可能性があることに気付きました。これは型のポイントを無効にします。そんなこと書いていいの?おそらく std::atomic はこの問題を解決しますが、コンパイラではアクセスできません...