Сообщение InterlockedExchange для enum от 09.09.2019 7:44
Изменено 09.09.2019 7:49 DDDX
InterlockedExchange для enum
Привет всем.
Хочу перейти на следующий уровень, но есть сомнения
Есть обычное перечисление — enum t_state{state__none,state__run,state__done};
Для переменной с типом t_state нужно замутить атомарный обмен значения.
std::atomic_exchange с enum работать не захотел, поэтому решил замутить велосипед.
Для атомарного обмена у меня есть штука вида:
Если я все правильно понимаю, в основе enum лежит 4-байтный int, LONG тоже 4-байтный. Поэтому можно (осторожно) заюзать InterlockedExchange(LONG*,LONG) для enum t_state.
У меня получился такая (пробная) реализация t_thread_traits__multi::exchange, которая работает как с LONG так и с enum:
Это не сильно корявое решение?
Промежуточный tag_exchange__std можно сократить, но пока это не принципиально.
Хочу перейти на следующий уровень, но есть сомнения
Есть обычное перечисление — enum t_state{state__none,state__run,state__done};
Для переменной с типом t_state нужно замутить атомарный обмен значения.
std::atomic_exchange с enum работать не захотел, поэтому решил замутить велосипед.
Для атомарного обмена у меня есть штука вида:
class t_thread_traits__multi
{
public: //---------------------------------------------------------------
static int_type exchange(volatile LONG* const target,LONG const value)
{
return ::InterlockedExchange(target,value);
}
};//class t_thread_traits__multi
Если я все правильно понимаю, в основе enum лежит 4-байтный int, LONG тоже 4-байтный. Поэтому можно (осторожно) заюзать InterlockedExchange(LONG*,LONG) для enum t_state.
У меня получился такая (пробная) реализация t_thread_traits__multi::exchange, которая работает как с LONG так и с enum:
//assert_s - это аналог static_assert
class t_thread_traits__multi
{
public: //---------------------------------------------------------------
template<typename T1,typename T2>
static T1 exchange(volatile T1* const target,T2 const value);
private:
template<typename T1>
class tag_exchange__enum;
template<typename T1,typename T2>
class tag_exchange__std;
template<typename T1,typename T2,size_t sizeOfT1>
class tag_exchange__std2;
template<typename T1,typename T2>
class tag_exchange__std2<T1,T2,4>;
};//class t_thread_traits__multi
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi
template<typename T1,typename T2>
inline T1 t_thread_traits__multi::exchange(volatile T1* const target,T2 const value)
{
typedef typename std::conditional<std::is_enum<T1>::value,tag_exchange__enum<T1>,tag_exchange__std<T1,T2> >::type
_e;
return _e::exec(target,value);
}//exchange
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi::tag_exchange__enum
template<typename T1>
class t_thread_traits__multi::tag_exchange__enum
{
public:
static T1 exec(volatile T1* const target,T1 const value)
{
typedef typename std::underlying_type<T1>::type _ut;
assert_s(sizeof(_ut)==sizeof(T1));
return static_cast<T1>(tag_exchange__std<_ut,_ut>::exec((_ut*)target,static_cast<_ut>(value)));
}//exec
};//struct t_thread_traits__multi::tag_exchange__enum
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi::tag_exchange__std
template<typename T1,typename T2>
class t_thread_traits__multi::tag_exchange__std
{
public:
static T1 exec(volatile T1* const target,T2 const value)
{
return tag_exchange__std2<T1,T2,sizeof(T1)>::exec(target,value);
}//exec
};//struct t_thread_traits__multi::tag_exchange__std
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi::tag_exchange__std2
template<typename T1,typename T2>
class t_thread_traits__multi::tag_exchange__std2<T1,T2,4>
{
public:
static T1 exec(volatile T1* const target,T2 const value)
{
assert_s(sizeof(T1)==4);
assert_s(sizeof(LONG)==4);
return (T1)::InterlockedExchange((LONG*)target,value);
}//exec
};//struct t_thread_traits__multi::tag_exchange__std2
Это не сильно корявое решение?
Промежуточный tag_exchange__std можно сократить, но пока это не принципиально.
InterlockedExchange для enum
Привет всем.
Хочу перейти на следующий уровень, но есть сомнения
Есть обычное перечисление — enum t_state{state__none,state__run,state__done};
Для переменной с типом t_state нужно замутить атомарный обмен значения.
std::atomic_exchange с enum работать не захотел, поэтому решил замутить велосипед.
Для атомарного обмена у меня есть штука вида:
Если я все правильно понимаю, в основе enum лежит 4-байтный int, LONG тоже 4-байтный. Поэтому можно (осторожно) заюзать InterlockedExchange(LONG*,LONG) для enum t_state.
У меня получился такая (пробная) реализация t_thread_traits__multi::exchange, которая работает как с LONG так и с enum:
Это не сильно корявое решение?
Промежуточный tag_exchange__std можно сократить, но пока это не принципиально.
UPD. Решение должно работать начиная с Visual Studio 2013.
Хочу перейти на следующий уровень, но есть сомнения
Есть обычное перечисление — enum t_state{state__none,state__run,state__done};
Для переменной с типом t_state нужно замутить атомарный обмен значения.
std::atomic_exchange с enum работать не захотел, поэтому решил замутить велосипед.
Для атомарного обмена у меня есть штука вида:
class t_thread_traits__multi
{
public: //---------------------------------------------------------------
static int_type exchange(volatile LONG* const target,LONG const value)
{
return ::InterlockedExchange(target,value);
}
};//class t_thread_traits__multi
Если я все правильно понимаю, в основе enum лежит 4-байтный int, LONG тоже 4-байтный. Поэтому можно (осторожно) заюзать InterlockedExchange(LONG*,LONG) для enum t_state.
У меня получился такая (пробная) реализация t_thread_traits__multi::exchange, которая работает как с LONG так и с enum:
//assert_s - это аналог static_assert
class t_thread_traits__multi
{
public: //---------------------------------------------------------------
template<typename T1,typename T2>
static T1 exchange(volatile T1* const target,T2 const value);
private:
template<typename T1>
class tag_exchange__enum;
template<typename T1,typename T2>
class tag_exchange__std;
template<typename T1,typename T2,size_t sizeOfT1>
class tag_exchange__std2;
template<typename T1,typename T2>
class tag_exchange__std2<T1,T2,4>;
};//class t_thread_traits__multi
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi
template<typename T1,typename T2>
inline T1 t_thread_traits__multi::exchange(volatile T1* const target,T2 const value)
{
typedef typename std::conditional<std::is_enum<T1>::value,tag_exchange__enum<T1>,tag_exchange__std<T1,T2> >::type
_e;
return _e::exec(target,value);
}//exchange
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi::tag_exchange__enum
template<typename T1>
class t_thread_traits__multi::tag_exchange__enum
{
public:
static T1 exec(volatile T1* const target,T1 const value)
{
typedef typename std::underlying_type<T1>::type _ut;
assert_s(sizeof(_ut)==sizeof(T1));
return static_cast<T1>(tag_exchange__std<_ut,_ut>::exec((_ut*)target,static_cast<_ut>(value)));
}//exec
};//struct t_thread_traits__multi::tag_exchange__enum
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi::tag_exchange__std
template<typename T1,typename T2>
class t_thread_traits__multi::tag_exchange__std
{
public:
static T1 exec(volatile T1* const target,T2 const value)
{
return tag_exchange__std2<T1,T2,sizeof(T1)>::exec(target,value);
}//exec
};//struct t_thread_traits__multi::tag_exchange__std
////////////////////////////////////////////////////////////////////////////////
//class t_thread_traits__multi::tag_exchange__std2
template<typename T1,typename T2>
class t_thread_traits__multi::tag_exchange__std2<T1,T2,4>
{
public:
static T1 exec(volatile T1* const target,T2 const value)
{
assert_s(sizeof(T1)==4);
assert_s(sizeof(LONG)==4);
return (T1)::InterlockedExchange((LONG*)target,value);
}//exec
};//struct t_thread_traits__multi::tag_exchange__std2
Это не сильно корявое решение?
Промежуточный tag_exchange__std можно сократить, но пока это не принципиально.
UPD. Решение должно работать начиная с Visual Studio 2013.