bugfix
Fixed a case where sometimes if the thread was created and then went out of scope too soon it would never get ran.
This commit is contained in:
@@ -14,7 +14,7 @@ namespace MultiThreading {
|
||||
class MultiThreading::Thread {
|
||||
private:
|
||||
std::thread worker;
|
||||
std::function<void()> current_task = nullptr;
|
||||
std::shared_ptr<TaskBase> current_task = nullptr;
|
||||
std::atomic<bool> busy = false;
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
@@ -22,13 +22,13 @@ private:
|
||||
private:
|
||||
void Runner();
|
||||
public:
|
||||
[[nodiscard]] bool SetTask(std::function<void()> task);
|
||||
[[nodiscard]] bool SetTask(const std::function<void()>& task);
|
||||
[[nodiscard]] bool SetTask(std::shared_ptr<TaskBase> task);
|
||||
[[nodiscard]] bool Busy() const { return busy; }
|
||||
void Join() { if (worker.joinable()) worker.join(); };
|
||||
public:
|
||||
Thread() { worker = std::thread([this] { this->Runner(); }); }
|
||||
explicit Thread(std::shared_ptr<TaskBase> task);
|
||||
explicit Thread(std::function<void()> task);
|
||||
explicit Thread(const std::function<void()>& task);
|
||||
~Thread();
|
||||
};
|
45
main.cpp
45
main.cpp
@@ -5,48 +5,53 @@
|
||||
#include <iostream>
|
||||
|
||||
using namespace MultiThreading;
|
||||
void some_test_func(int32_t hello) {
|
||||
for (unsigned int i = 0; i < 400; i++)
|
||||
std::cout << "test" << std::endl;
|
||||
int32_t some_test_func(int32_t hello) {
|
||||
for (unsigned int i = 0; i < 100; i++)
|
||||
std::cout << i << std::endl;
|
||||
return hello;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
int main() {
|
||||
// Each task you create can be run by a thread only once. It's marked as complete after.
|
||||
// If you're running a lambda or std::function directly on the thread, It can be used multiple times.
|
||||
int32_t a = 0;
|
||||
auto some_task = Task<void>::Create([] { return some_test_func(4); });
|
||||
auto some_task = Task<int32_t>::Create([] { return some_test_func(4); }, &a);
|
||||
|
||||
// You can start threads in place like this, but you have to wait for the amount of time
|
||||
// it takes for the thread to start up which in many cases is longer than the job. Use thread pool.
|
||||
Thread some_thread(some_task);
|
||||
Thread some_thread;
|
||||
some_thread.SetTask(some_task);
|
||||
|
||||
// Some work running concurrently with the worker thread.
|
||||
for (unsigned int i = 0; i < 1000000000; i++) {}
|
||||
//for (unsigned int i = 0; i < 10; i++) {}
|
||||
|
||||
// When we get to the point in our code where we need the result from the task wait until it's finished.
|
||||
while (!some_task->Complete()) {}
|
||||
//while (!some_task->Complete()) {}
|
||||
|
||||
// At this point, the thread is sleeping and a new task can be pushed on.
|
||||
auto some_other_task = Task<void>::Create(std::bind(some_test_func, 5));
|
||||
|
||||
if (!some_thread.SetTask(some_other_task))
|
||||
throw std::runtime_error("Error while pushing the task on-to the thread");
|
||||
std::cout << some_thread.Busy() << std::endl;
|
||||
|
||||
// Because the thread exists already and is waiting for jobs, We don't get the penalty of the thread start-up time.
|
||||
while (!some_other_task->Complete()) { std::cout << some_thread.Busy() << std::endl; }
|
||||
|
||||
std::cout << a << std::endl;
|
||||
//std::cout << a << std::endl;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
int main() {
|
||||
ThreadPool thread_pool(1);
|
||||
|
||||
auto some_task_1 = Task<void>::Create(([] { return some_test_func(1); }));
|
||||
auto some_task_2 = Task<void>::Create(([] { return some_test_func(1); }));
|
||||
auto some_task_3 = Task<void>::Create(([] { return some_test_func(1); }));
|
||||
auto some_task_4 = Task<void>::Create(([] { return some_test_func(1); }));
|
||||
|
||||
thread_pool.Enqueue(some_task_1);
|
||||
thread_pool.Enqueue(some_task_2);
|
||||
thread_pool.Enqueue(some_task_3);
|
||||
thread_pool.Enqueue(some_task_4);
|
||||
|
||||
while (!some_task_4->Complete()) {}
|
||||
std::cout << thread_pool.ThreadCount() << std::endl;
|
||||
|
||||
//delete thread_pool;
|
||||
}
|
||||
}
|
||||
*/
|
@@ -6,34 +6,28 @@
|
||||
using namespace MultiThreading;
|
||||
|
||||
Thread::~Thread() {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
stop = true;
|
||||
current_task = nullptr;
|
||||
}
|
||||
|
||||
cv.notify_all();
|
||||
if (current_task)
|
||||
while (!current_task->Complete()) {}
|
||||
stop = true;
|
||||
Join();
|
||||
// Thread exits gracefully.
|
||||
}
|
||||
|
||||
bool Thread::SetTask(std::shared_ptr<TaskBase> task) {
|
||||
return Thread::SetTask([task]{ task->Run(); });
|
||||
}
|
||||
|
||||
bool Thread::SetTask(std::function<void()> task) {
|
||||
if (busy)
|
||||
return false;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
current_task = std::move(task);
|
||||
}
|
||||
cv.notify_all();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Thread::SetTask(const std::function<void()>& task) {
|
||||
return SetTask(Task<void>::Create(task));
|
||||
}
|
||||
|
||||
void Thread::Runner() {
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
while (!stop) {
|
||||
@@ -42,16 +36,15 @@ void Thread::Runner() {
|
||||
if (stop)
|
||||
break;
|
||||
|
||||
auto this_task = std::move(current_task);
|
||||
current_task = nullptr;
|
||||
|
||||
busy = true;
|
||||
|
||||
lock.unlock();
|
||||
if (this_task)
|
||||
this_task();
|
||||
if (current_task)
|
||||
current_task->Run();
|
||||
|
||||
lock.lock();
|
||||
|
||||
current_task = nullptr;
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
@@ -59,13 +52,13 @@ void Thread::Runner() {
|
||||
Thread::Thread(std::shared_ptr<TaskBase> task) {
|
||||
worker = std::thread([this] { this->Runner(); });
|
||||
|
||||
if (!SetTask(task))
|
||||
throw std::runtime_error("Thread constructor failure.");
|
||||
}
|
||||
|
||||
Thread::Thread(std::function<void()> task) {
|
||||
worker = std::thread([this] { this->Runner(); });
|
||||
|
||||
if (!SetTask(std::move(task)))
|
||||
throw std::runtime_error("Thread constructor failure.");
|
||||
}
|
||||
|
||||
Thread::Thread(const std::function<void()>& task) {
|
||||
worker = std::thread([this] { this->Runner(); });
|
||||
|
||||
if (!SetTask(task))
|
||||
throw std::runtime_error("Thread constructor failure.");
|
||||
}
|
||||
|
Reference in New Issue
Block a user