Consider the below code, this shall be a minimal sample of my question:
class TaskMgr {
public:
// This is a threadsafe and lockfree queue implementation
static concurrent_list_impl<std::string> Tasks;
std::atomic<bool> mRun;
std::atomic<bool> mStart;
public:
TaskMgr() {mStart = mRun = false;}
~TaskMgr() {}
void run() {
mStart = true;
while (!mEnd) {
//PROCESS QUEUE TASKS
std::string task;
while (Tasks.try_dequeue(task)) {
// DO STH WITH TASK
}
//FINISHING, CLOSING RESOURCES #1
mEnd = true;
}
}
};
TaskMgr tm;
void addTask(std::string task) {
tm.Tasks.enqueue(task);
if (tm.mEnd || !tm.mStart) boost::thread(boost::bind(&TaskMgr::run, tm)); #2
}
int main()
{
addTask("TASK1"); //OK
sleep(1);
addTask("TASK2"); //Does not create new thread, because tm.mEnd == false && tm.mStart == true
sleep(5);
addTask("TASK3"); //OK, and manager will handle both TASK2 and TASK3
sleep(15);
}
So I have a Task manager which handles string tasks. Task is a concurrent thread-safe and lock-free queue implementation, that shall reduces the locking and synchronization overhead.
But still, this example have at least one problem I see:
If #2 checks the mEnd atomic just during the thread is executing the #1: colsing resources, mEnd is still false, and mStart is true, so a new thread will not be created, and "TASK2" will only be handled once a new item is added which actually triggers the thread creation.
I don't want a thread to constantly running, tasks frequency is low, but I also don't want to lose tasks, and if possible try to keep overhead as low as possible.