在现代C++中,我正在实现线程管理员。我所得到的是有用的,虽然它还没有按照我想要的方式组织起来,但我想要一些关于基本面的反馈。提前感谢您的所有提示。=)
所有线程(包括main()以向程序结束发送信号)都通过以下方式共享数据:
#ifndef SHAREDDATA_HPP
#define SHAREDDATA_HPP
#include <condition_variable>
#include <thread>
class SharedData {
public:
std::mutex keypress_mutex;
std::condition_variable keypress_cv;
bool keypress_flag;
std::mutex thread_count_mutex;
std::condition_variable thread_count_cv;
unsigned int thread_count;
std::mutex thread_kill_mutex;
std::condition_variable thread_kill_cv;
bool thread_kill_flag;
SharedData():
keypress_flag{false},
thread_count{0},
thread_kill_flag{false}
{ }
~SharedData() = default;
};
#endif // SHAREDDATA_HPP然后我们找了个小RAII来帮助跟踪线程数:
#ifndef THREADCOUNTER_HPP
#define THREADCOUNTER_HPP
#include <thread>
class SharedData;
class ThreadCounter {
public:
explicit ThreadCounter(SharedData *share);
~ThreadCounter();
private:
SharedData *_share;
};
#endif // THREADCOUNTER_HPP
//--------------------------
#include "ThreadCounter.hpp"
#include "SharedData.hpp"
ThreadCounter::ThreadCounter(SharedData *share) :
_share{share}
{
std::lock_guard<std::mutex> _lock(_share->thread_count_mutex);
share->thread_count++;
}
ThreadCounter::~ThreadCounter() {
std::lock_guard<std::mutex> _lock(_share->thread_count_mutex);
_share->thread_count--;
if(_share->thread_count == 0) {
_share->thread_count_cv.notify_one();
}
}接下来,ManagedThread类本身:
#ifndef MANAGEDTHREAD_HPP
#define MANAGEDTHREAD_HPP
#include <thread>
class SharedData;
class ManagedThread {
public:
void launch();
explicit ManagedThread(SharedData *share);
~ManagedThread();
ManagedThread() = delete;
void operator()();
private:
SharedData *_share;
std::thread _thread;
};
#endif // MANAGEDTHREAD_HPP
//--------------------------
#include "ManagedThread.hpp"
#include "SharedData.hpp"
#include "ThreadCounter.hpp"
#include <chrono>
#include <iostream>
#include <cassert>
using namespace std::chrono_literals;
void ManagedThread::launch() {
if(!_thread.joinable()) {
_thread = std::thread(std::ref(*this));
}
else {
assert((false) && "Managed Thread not launchable!");
}
}
ManagedThread::ManagedThread(SharedData *share) :
_share{share},
_thread{std::thread()}
{ }
ManagedThread::~ManagedThread() {
if(_thread.joinable()) {
_thread.join();
}
}
void ManagedThread::operator()() {
ThreadCounter tc(_share);
while(true) {
std::this_thread::sleep_for(250ms);
std::cout << "Whee!" << std::endl;
std::unique_lock<std::mutex> kill_lock(_share->thread_kill_mutex);
if(_share->thread_kill_cv.wait_for(kill_lock, 100ms,
[&](){ return _share->thread_kill_flag; })) {
break;
}
}
}以及负责清理协调的ThreadManager:
#ifndef THREADMANAGER_HPP
#define THREADMANAGER_HPP
class SharedData;
class ThreadManager {
public:
explicit ThreadManager(SharedData *share) : _share{share} { };
~ThreadManager() = default;
void operator()();
private:
SharedData *_share;
};
#endif // THREADMANAGER_HPP
//--------------------------
#include "ThreadManager.hpp"
#include "SharedData.hpp"
#include <chrono>
using namespace std::chrono_literals;
void ThreadManager::operator()() {
std::this_thread::sleep_for(25ms);
std::unique_lock<std::mutex> keypress_lock(_share->keypress_mutex);
_share->keypress_cv.wait(keypress_lock,
[&](){ return _share->keypress_flag; });
keypress_lock.unlock();
{
std::lock_guard<std::mutex> kill_lock(_share->thread_kill_mutex);
_share->thread_kill_flag = true;
}
_share->thread_kill_cv.notify_all();
std::unique_lock<std::mutex> count_lock(_share->thread_count_mutex);
_share->thread_count_cv.wait(count_lock,
[&](){ return _share->thread_count == 0; });
}最后,一个main.cpp把它连接在一起。
#include "SharedData.hpp"
#include "ThreadManager.hpp"
#include "ManagedThread.hpp"
#include <iostream>
#include <future>
int main() {
SharedData share;
ThreadManager tm(&share);
ManagedThread t0(&share);
t0.launch();
std::future<void> cf = std::async(std::launch::async, std::move(tm));
int input;
std::cin >> input;
{
std::lock_guard<std::mutex> lock(share.keypress_mutex);
share.keypress_flag = true;
}
share.keypress_cv.notify_one();
cf.get();
return 0;
}我知道我不喜欢的是ThreadManager并不拥有SharedData。我还希望ThreadManager能够泛化地管理继承的线程中的任何ManagedThread,甚至可能是重载的operator(),这样可调用的线程可以做任何事情,但仍然是“管理”的。
在这一点上,这些只是思考--我真正想知道的是,到目前为止,这个系统实现得有多好或有多差。=)
再次感谢您的反馈,我期待着改进这个设置并在将来利用它。
发布于 2021-10-28 18:23:39
您正在通过指针传递SharedData。如果通过引用来传递它的话会更干净:
class ThreadCounter {
public:
explicit ThreadCounter(SharedData& share);
~ThreadCounter();
private:
SharedData& _share;
};lock.。
当您只需使用原子变量时,锁定是昂贵和过于复杂的:
struct SharedData
{
std::atomic<bool> keypress_flag = false;
}
int main() {
SharedData share;
// start threads
int input;
std::cin >> input;
share.keypress_flag = true;
// join threads
}std::endl刷新输出。您不必使用\n:
std::cout << "Whee!\n";我不太清楚你想做什么。在我看来,您可以用以下简单的内容替换所有代码:
#include <atomic>
#include <iostream>
#include <thread>
std::atomic_bool running = true;
void func()
{
using namespace std::chrono_literals;
while (running)
{
std::this_thread::sleep_for(250ms);
std::cout << "Whee!\n";
}
}
int main()
{
std::thread thread(func);
int input;
std::cin >> input;
running = false;
thread.join();
}https://codereview.stackexchange.com/questions/269462
复制相似问题