Fixed a timing bug

That would cause the thread to not be reported as busy while putting the task on-to the thread.
This commit is contained in:
2025-04-09 16:37:55 -04:00
parent a03eb39347
commit 3b9ca2e144
3 changed files with 36 additions and 16 deletions

View File

@@ -5,6 +5,7 @@
#include <stdexcept>
#include <condition_variable>
#include <mutex>
#include <utility>
#include <MultiThreading/Task.h>
namespace MultiThreading {
@@ -13,12 +14,13 @@ namespace MultiThreading {
class MultiThreading::Thread {
private:
std::thread worker;
std::function<void(Thread* thread, std::shared_ptr<TaskBase> task)> on_task_complete_callback = nullptr;
std::shared_ptr<TaskBase> current_task = nullptr;
std::atomic<bool> busy = false;
std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> stop = false;
std::condition_variable cv;
std::thread worker;
std::mutex mtx;
bool busy = false;
private:
void Runner();
public:
@@ -26,6 +28,7 @@ public:
[[nodiscard]] bool SetTask(std::shared_ptr<TaskBase> task);
[[nodiscard]] bool Busy() const { return busy; }
void Join() { if (worker.joinable()) worker.join(); };
void SetTaskCompletionCallback(std::function<void(Thread*, std::shared_ptr<TaskBase>)> callback) { on_task_complete_callback = std::move(callback); };
public:
Thread() { worker = std::thread([this] { this->Runner(); }); }
explicit Thread(std::shared_ptr<TaskBase> task);

View File

@@ -6,11 +6,15 @@
using namespace MultiThreading;
int32_t some_test_func(int32_t hello) {
for (unsigned int i = 0; i < 100; i++)
for (unsigned int i = 0; i < 50; i++)
std::cout << i << std::endl;
return hello;
}
void cb(Thread* thread, std::shared_ptr<TaskBase> task) {
std::cout << thread->Busy() << std::endl;
std::cout << task->Complete() << std::endl;
}
int main() {
// Each task you create can be run by a thread only once. It's marked as complete after.
@@ -21,8 +25,14 @@ int main() {
// 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_thread.SetTaskCompletionCallback(cb);
some_thread.SetTask(some_task);
//while (!some_task->Complete()) {}
//std::this_thread::sleep_for(std::chrono::milliseconds(1));
std::cout << some_thread.Busy() << std::endl;
// Some work running concurrently with the worker thread.
//for (unsigned int i = 0; i < 10; i++) {}

View File

@@ -1,6 +1,4 @@
#include <MultiThreading/Thread.h>
#include <sstream>
#include <iostream>
#include <utility>
using namespace MultiThreading;
@@ -9,17 +7,24 @@ Thread::~Thread() {
if (current_task)
while (!current_task->Complete()) {}
stop = true;
cv.notify_one();
Join();
// Thread exits gracefully.
}
bool Thread::SetTask(std::shared_ptr<TaskBase> task) {
if (busy)
std::lock_guard<std::mutex> lock(mtx);
if (Busy())
return false;
{
std::lock_guard<std::mutex> lock(mtx);
current_task = std::move(task);
}
if (current_task)
return false;
busy = true;
current_task = std::move(task);
cv.notify_all();
return true;
}
@@ -30,17 +35,19 @@ bool Thread::SetTask(const std::function<void()>& task) {
void Thread::Runner() {
std::unique_lock<std::mutex> lock(mtx);
while (!stop) {
cv.wait(lock, [this] { return stop || current_task != nullptr; });
if (stop)
break;
busy = true;
lock.unlock();
if (current_task)
current_task->Run();
current_task->Run();
if (on_task_complete_callback)
on_task_complete_callback(this, current_task);
lock.lock();