当执行绪必须不断去执行某项工作,也就是thread里面包含while,此用法常见于将工作平行化及背景化。
情境假设,有项工作分别有三个阶段:开始(start)、执行(loop)、结束(stop)。简单的作法可能如下。
void thread_simple() {start();while (condiction) loop();stop();}
情境升级!
有项工作分别有三个阶段:开始(start)、执行(loop)、结束(stop),呼叫时机点可由外部决定。或许为此设计出一个class如下。
class worker_simple {public:int Start() { ... }int Stop() { ... }void StartThread() {condiction = true;thread = new std::thread(&worker_simple::Loop, this);}int Loop() {while (condiction) { ... }}private:std::thread *thread;};
情境再升级!最终版!
有项工作分别有三个阶段:开始(start)、执行(loop)、结束(stop),呼叫时机点可由外部决定。所有工作都必须在同一条执行绪上执行。
下列这个範例都写在同一个cpp档,方便複製贴上后可直接执行。此範例支援工作阶段的无限扩充,(但型别受限于std::function),欢迎指教是否有更好作法。
#include <functional>#include <iostream>#include <thread>#include <mutex>#include <chrono>class Worker {public:Worker() {is_thread_alive = true;thread = new std::thread(&Worker::thread_main, this);}~Worker() {cfit.wait_result([this]() {is_thread_alive = false;is_run_main = false;return 0;});thread->join();delete thread;}int Start() {return cfit.wait_result(std::bind<int>(&Worker::start, this));}int Stop() {return cfit.wait_result(std::bind<int>(&Worker::stop, this));}private:std::thread *thread;bool is_thread_alive = false;bool is_run_main = false;void thread_main() {while (is_thread_alive) {cfit.call_function();if (is_run_main) loop();}}int start() {is_run_main = true;printf("%s\n", __func__);return 0;}int stop() {is_run_main = false;printf("%s\n", __func__);return 0;}void loop() {printf("%s %d\n", __func__, clock());std::this_thread::sleep_for(std::chrono::milliseconds(1000));}template<class T>class call_func_in_thread {public:T wait_result(std::function<T()> func) {std::unique_lock<std::mutex> lock(mutex);one_time_lock = false;function = func;request.notify_all(); // send a request and wait the replyreply.wait(lock, [this] { return function == nullptr; });lock.unlock();return result;}void call_function() {std::unique_lock<std::mutex> lock(mutex); // wait for a request and execute function if it existsrequest.wait(lock, [this] { return !one_time_lock; });if (function != nullptr) {result = function();function = nullptr;reply.notify_all();}lock.unlock();}private:std::function<int()> function;std::condition_variable request, reply;std::mutex mutex;bool one_time_lock = true;T result;};call_func_in_thread<int> cfit;};int main(){Worker *worker = new Worker();while (true) {char c = getchar();if (c == 'e') break;else if (c == '1') worker->Start();else if (c == '2') worker->Stop();else if (c == '3') delete worker;}return 0;}