私は単純なスレッドプールの実装を持っています。実装は以下の通りですプッシュが成功したにもかかわらず、プッシュされたアイテムでスレッドプールキューが更新されていません
問題は、キューに項目を挿入したときにスレッドプールの機能に反映されない場合です。void worker_thread()つまりworker_thread()のif(work_queue.try_pop(task)関数は常に失敗し、スレッドによってタスクが選択されません。 私は間違っていることを指摘できますか?
ありがとうございます。
template<typename T>
class threadsafe_queue
{
private:
mutable std::mutex mut;
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue()
{}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(std::move(new_value));
data_cond.notify_one();
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this]{return !data_queue.empty(); });
value = std::move(data_queue.front());
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk, [this]{return !data_queue.empty(); });
std::shared_ptr<T> res(
std::make_shared<T>(std::move(data_queue.front())));
data_queue.pop();
return res;
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return false;
value = std::move(data_queue.front());
data_queue.pop();
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if (data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(
std::make_shared<T>(std::move(data_queue.front())));
data_queue.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
class thread_pool
{
threadsafe_queue<std::function<void()>> work_queue;
std::atomic<bool> done;
int thread_count;
std::vector<std::thread> threads;
void worker_thread()
{
while (!done)
{
std::function<void()> task;
if (work_queue.try_pop(task)) // here work_queue is always empty.
{
task();
}
else
{
std::this_thread::yield();
}
}
}
public:
thread_pool(unsigned thread_count = 5) : done(false), thread_count(thread_count)
{
try
{
for (unsigned i = 0; i < thread_count; ++i)
{
threads.emplace_back(std::thread(&thread_pool::worker_thread, this));
}
}
catch (...)
{
done = true;
throw;
}
}
~thread_pool()
{
done = true;
for (unsigned i = 0; i < thread_count; ++i)
{
threads[i].join();
}
}
template <typename FunctionType>
void submit(FunctionType f)
{
work_queue.push(std::function<void()>(f)); // this shows proper size of queue after push.
}
};
void fun()
{
cout << "hi"<<this_thread::get_id(); // this funciton is never being executed by thread pool.
}
template<class T>
class A
{
private:
int x{ 3 };
public:
void fun(vector<string> &v) // this funciton is never being executed by thread pool.
{
std::cout << v[0].c_str() << endl;
x = 5;
}
}
int main()
{
thread_pool tp(2);
vector<string> v{ "1", "2" };
A<int> a;
tp.submit([&] { a.fun(std::ref(v)); });
tp.submit < void()>(fun);
std::this_thread::sleep_for(std::chrono::seconds(10));
return 0;
}
制御 は非void型関数[-Wreturn型]の最後に到達しますか?第2に、あなたのキューに 'abort()'機能を持たせることは便利です。これは、キューが満了していることをスレッドに伝えるために使用できます。原則として、作業がないときは、何もする必要はありません。作業がない場合でも作業スレッドごとに1つのCPUが必要です。 – Yakk