Класс с двумя перегруженными operator()
функции вызываются из отдельных потоков. Смотрите // комментарии в коде ниже.
Оптимизатор знает не двигаться entryadd = mSpread * ENTRY_MULTIPLIER
выше lock()
?
struct Algo1
{
boost::detail::spinlock mSpreadLock;
Algo1() : mSpreadLock() {}
//called from thread 1
inline void operator()(const indata &signal)
{
if ( signal.action() == SEND )
{
double entryadd;
mSpreadLock.lock();
entryadd = mSpread * ENTRY_MULTIPLIER; //isnt it possible for compiler to optimize this before the lock?
mSpreadLock.unlock();
FunctionCall(entryadd);
}
}
//called from thread2
inline void operator()(const indata2 &bospread)
{
boost::detail::spinlock::scoped_lock mylock(mSpreadLock);
mSpread = bospread.spread();
}
}
Как насчет этого?
{
mSpreadLock.lock();
double entryadd = mSpread * ENTRY_MULTIPLIER;
mSpreadLock.unlock();
{
Будет ли определение entryadd
я перешел на вершину функции?
Если я что-то упустил .. кажется, что блокировка и разблокировка в блоке кода не будет работать. должен использовать scoped_lock. boost::detail::spinlock::scoped_lock mylock(mSpreadLock)
, который будет блокироваться на время вызова функции.
Конечно, я могу просто взломать это так: (но менее эффективно)
inline void operator()(const indata &signal)
{
if ( signal.action() == SEND )
{
double entryadd;
{
boost::detail::spinlock::scoped_lock mylock(mSpreadLock);
entryadd = mSpread * ENTRY_MULTIPLIER;
}
FunctionCall(entryadd);
}
}
Операции блокировки в конечном итоге будут использовать встроенные функции компилятора, которые выполняют некоторый тип атомарных операций. Компилятор знает, что эти операции не должны быть перезаписаны, и не будет оптимизировать «прошлое». Все хорошо.
Других решений пока нет …