Я пытаюсь написать класс-оболочку для обертки внутренней функции Win32, такой как InterlockedIncrement
, 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
после выполнения операции блокировки позволяет использовать другой поток для изменения переменной до ее возврата. Это аннулирует точку типа. Можно ли написать такое? Предположительно станд :: атомными решает эту проблему, но у меня нет доступа к, что в моем компиляторе ...
Спасибо, что я не знал об «boost :: atomic». Хотя мне все же хотелось бы знать, как это возможно в теории. – Benj
@Benj: Хорошо, вижу. Вы можете посмотреть, как это реализовано в Boost. – nogard