У меня есть следующий код:
MyClass::aMethod()
{
...
bool isStarted = false;
boost::thread(boost::bind(&MyClass::CheckTimeoutThread, this, isStarted));
...//some time later
isStarted = true;
...
}
MyClass::checkTimeoutThread(bool &isStarted)
{
...//some code here
while(anotherFlag)
{
...//do something
if(isStarted)//ALWAYS THE INITIAL VALUE OF FALSE
{
}
...
}
}
Я ожидал isStarted переменная может быть использована как флаг, но я ошибаюсь или я что-то не так делаю.
boost::thread
будет хранить копию своих аргументов. Но вы можете смоделировать ссылку, передав reference_wrapper
с помощью boost::ref
, Также обратите внимание, что вам не нужно звонить boost::bind
:
boost::thread t(&MyClass::CheckTimeoutThread, this, boost::ref(isStarted));
Но обратите внимание, что теперь у вас есть условия гонки на isStarted
, Вам нужно либо синхронизировать доступ к нему, скажем, с мьютексами, либо использовать атомарный тип, если он доступен на вашей платформе (если у вас есть C ++ 11, вы можете использовать std::atomic<bool>
, как предложено @PeteBecker.)
редактировать Очевидно, все вышеперечисленное предполагает, что isStated
живет по крайней мере до тех пор, пока thread
который использует это. На практике это означает, что поток должен быть сделан ко времени aMethod
возвращается. Кроме того, вы можете сделать isStarted
член данных. Но вы все равно должны обязательно присоединиться к ветке до того, как MyClass
деструктор уничтожает его.
Самая большая проблема (кроме std::ref
или же boost::ref
требуется передать ссылки на thread
), что вы передаете ссылка на временный
MyClass::aMethod()
{
...
bool isStarted = false;
}
/// Oops at the end of the method, `isStarted` no longer lives
Любой доступ через устаревшая ссылка Неопределенное поведение после того, как контроль уходит aMethod
Могу ли я предложить использовать правильную синхронизацию: Посмотреть это в прямом эфире на Coliru
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
struct X
{
std::condition_variable cv;
std::mutex mx;
bool isStarted;
std::thread worker;
X() : isStarted(false) {}
void aMethod()
{
worker = std::thread(&X::Worker, this);
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::cout << "signalling worker\n";
std::unique_lock<std::mutex> lock(mx);
isStarted = true;
cv.notify_one();
}
worker.join();
isStarted = false;
}
void Worker()
{
std::unique_lock<std::mutex> lock(mx);
std::cout << "worker ready\n";
cv.wait(lock, [this] { return isStarted; });
std::cout << "worker started\n";
std::cout << "worker done\n";
}
};
int main()
{
X o;
o.aMethod();
}
Обратите внимание, что
s/std/boost
Вы должны быть в состоянии использовать это на компиляторах C ++ 03isStarted
больше в этом случае. Я добавил это из-за ложных пробуждений: Почему pthread_cond_wait имеет ложные пробуждения?