Да: Boost.Thread отлично, и должно соответствовать вашим потребностям очень хорошо. (В наши дни многие говорят, что вы можете считать Boost встроенной функциональностью.)
По-прежнему нет класса, который можно было бы использовать «из коробки», но как только у вас есть примитивы синхронизации, на самом деле довольно просто реализовать свой собственный потокобезопасный упаковщик, например, std::stack
. Это может выглядеть примерно так (не реализуя каждый метод ...):
template <typename T> class MyThreadSafeStack {
public:
void push(const T& item) {
boost::mutex::scoped_lock lock(m_mutex);
m_stack.push(item);
}
void pop() {
boost::mutex::scoped_lock lock(m_mutex);
m_stack.pop();
}
T top() const { // note that we shouldn't return a reference,
// because another thread might pop() this
// object in the meanwhile
boost::mutex::scoped_lock lock(m_mutex);
return m_stack.top();
}
private:
mutable boost::mutex m_mutex;
std::stack<T> m_stack;
}
Если вы новичок в C ++, изучите RAII . Относящийся к этому случаю, Boost.Thread имеет классы «блокировки прицела», которые затрудняют попадание в ногу, забывая снять блокировку.
Если вы когда-нибудь будете писать код, подобный этому:
void doStuff() {
myLock.lock();
if (!condition) {
reportError();
myLock.unlock();
return;
}
try {
doStuffThatMayThrow();
}
catch (std::exception& e) {
myLock.unlock();
throw e;
}
doMoreStuff();
myLock.unlock();
}
, тогда вы должны просто сказать «нет» и перейти вместо RAII (синтаксис не напрямую из Boost):
void doStuff() {
scoped_lock lock;
if (!condition) {
reportError();
return;
}
doStuffThatMayThrow();
doMoreStuff();
}
Дело в том, что когда объект scoped_lock
выходит из области видимости, его деструктор освобождает ресурс - в данном случае блокировку. Это всегда будет происходить независимо от того, выйдете ли вы из области видимости, вызвав исключение или выполнив нечетное выражение return
, которое ваш коллега украдкой добавил в середине вашей функции, или просто достигнув конца функции.