I have the task of initialisation of an object, that is quite long. What is the right way to go about it?
here is the code i have so far (for simplicity, initialisation consists of adding entries to string list only):
#ifndef TASKINITIALIZER_H
#define TASKINITIALIZER_H
#include <QDir>
#include <QThread>
#include <QObject>
#include "task.h"
class TaskInitializer:public QThread
{
Q_OBJECT
QDir dir;
QString msg;
Task &result;
public:
TaskInitializer(QString dname, bool png, bool jpg, bool bmp, Task &res);
~TaskInitializer();
const QString& getMessage();
bool isOk();
private:
void run();
};
#endif // TASKINITIALIZER_H
#include <QDir>
#include <QDirIterator>
#include "taskinitializer.h"
TaskInitializer::TaskInitializer(QString dname, bool png, bool jpg, bool bmp, Task & res):
dir(dname),result(res)
{
QStringList filters;
if (png)
filters << "*.png";
if(jpg)
{
filters << "*.jpeg" << "*.jpg";
}
if(bmp)
filters << "*.bmp";
dir.setNameFilters(filters);
}
TaskInitializer::~TaskInitializer()
{
}
const QString &TaskInitializer::getMessage()
{
return msg;
}
bool TaskInitializer::isOk()
{
if (!dir.exists())
{
msg = ("Directory does not exist");
return false;
}
if (dir.nameFilters().length() < 1)
{
msg = ("No image types chosen");
return false;
}
return true;
}
void TaskInitializer::run()
{
QDirIterator di(dir,QDirIterator::Subdirectories);
while(di.hasNext())
{
result.addFilename(di.next());
}
}
The ides is to pass parameters to initialiser instance in constructor, check their validity and then run the initialisation itself. However, initialisation may take long and the application may be stopped abruptly; in this case initialiser should stop its activity properly and be cleaned up.
I have read on several methods of running async tasks, but still haven't understood how to detect the stop signal. As far as i can see, running QRunnable in thread pool or using QtConcurrent::run() does not gives any mechanism of checking whether it is time to stop or not.
Also, i am confused of the subject of how to pass the object being initialised properly to and from initialising task, so that it would be guaranteed to be cleaned up. Same with initialiser; how can it be guaranteed to be cleaned up?
here is the code i currently use to launch initialisation:
_temp = new Task();
TaskInitializer *worker = new TaskInitializer(_directoryName,flags[2],flags[1],flags[0],*_temp);
if (!worker->isOk())
{
delete _temp;
_temp = NULL;
emit logMessage(worker->getMessage());
return _temp;
}
//clearTempTask();
emit logMessage("New task created");
connect(worker,SIGNAL(finished()),SIGNAL(taskInitialized()));
connect(worker,SIGNAL(finished()),worker,SLOT(deleteLater()));
worker->start();
worker = NULL;
Well, the quick-and-dirty method would be to have a boolean variable (named pleaseStop or something) that the initializer thread checks every so often to see if the main thread has set it to true or not. If the main thread has set it to true, the thread task would see that and abort its initialization routine and exit.
A slightly nicer method would be to break up the initialization task into smaller parts -- e.g. do 50 milliseconds worth of initialization, then if there is still more initialization left to do, call QTimer::singleShot(0, this, SLOT(DoSomeMore()) and return from the method, such that the DoSomeMore() slot gets called on the next iteration of the Qt event loop, but in the meantime any other pending signals (such as a PleaseQuitNow() type of signal coming in from the main thread, which could be connected to the QThread's quit() slot) would get processed.
In fact, if you keep the time slices short enough, with the second method you may not even need to launch a second thread at all -- the initialization could run in the main thread but GUI events would still get serviced in a relatively timely manner, since they would get interspersed between short DoSomeMore() calls rather than being blocked by a single very lengthy DoEverythingAllInOneGo() call.
As for passing the data object back and forth, simply handing the initializer thread a pointer/reference to the data object is sufficient, as long as you are careful to ensure the following:
The main thread shouldn't read or write the data object until the initializer thread has completed its work
The main thread must guarantee that the data object will remain valid until after the initializer thread has completed its work (e.g. don't delete the data object while the initializer thread might still be using it!)
Related
I have got a class named cApp.
I want to run CheckProcessList() in the background until the program terminates. So i thought, well, lets run it in a detached thread until ~cApp(). I made a bool to break out of the loop in CheckProcessList(). In ~cApp I set the bool true m_bTerminateThread = true to break out and wait for the promise m_barrierFuture->wait() that the thread has ended execution. After breaking out i set the promise barrier.set_value() that the thread is now ending execution. Now ~cApp can finish execution. Or at least that is my understanding of the things i want to achieve and how to do it. Well, can't be right since i get Compiler Errors.
Why did it want to check if the thread finished in the first place? Because the program breaks at runtime when it terminates and the thread is at that moment in GetProcId(). If it is sleeping in the moment of termination the program does not break.
I searched msdn and stackoverflow for answers but i do not get anything out of it that i can understand. I am using VS2019 and C++14. Thank you guys in advance.
cApp.h
#pragma once
#include "wx/wx.h"
#include "cMain.h"
#include <thread>
#include <future>
class cApp
: public wxApp
{
public:
cApp();
~cApp();
virtual bool OnInit();
private:
// supposed to run in a detached thread
// until the program terminates
void CheckProcessList(std::promise<void> barrier);
// Checks whether or not the game processes are running
// this thread runs asynchronous until ~cApp
std::thread* m_tCheckProcList;
// used in thread "m_tCheckProcList"
// if set to true the thread terminates asap
bool m_bTerminateThread;
// used in thread "m_tCheckProcList"
// in ~cApp this future waits for the promise that the thread has finished
std::future<void>* m_barrierFuture;
// Dark Souls 3 Processname
const wchar_t* m_ds3Name;
// Need for Speed: Most Wanted Processname
const wchar_t* m_nfsmwName;
// Serious Sam: The Second Encounter Processname
const wchar_t* m_sstseName;
const wxString* m_frameTitle;
const wxSize* m_frameSize;
cMain* m_mainFrame;
};
cApp.cpp
#include "cApp.h"
wxIMPLEMENT_APP(cApp);
cApp::cApp()
{
m_ds3Name = L"DarkSoulsIII.exe";
m_sstseName = L"SeriousSam.exe";
m_nfsmwName = L"speed.exe";
m_frameTitle = new wxString("DeltaWin");
m_frameSize = new wxSize(600, 450);
m_bTerminateThread = false;
m_mainFrame = nullptr;
m_tCheckProcList = nullptr;
m_barrierFuture = nullptr;
}
cApp::~cApp()
{
// send the thread the "signal" to finish asap
m_bTerminateThread = true;
// wait for thread "m_tCheckProcList" to finish execution
m_barrierFuture->wait();
}
bool cApp::OnInit()
{
// create main top-level window
m_mainFrame = new cMain(*m_frameTitle, wxDefaultPosition, *m_frameSize);
m_mainFrame->Show();
// create barrier and instantiate the future for it
std::promise<void> barrier;
m_barrierFuture = new std::future<void>(barrier.get_future());
// start checking for running game processes in asynchronous thread
m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
m_tCheckProcList->detach();
return true;
}
void cApp::CheckProcessList(std::promise<void> barrier)
{
while (!m_bTerminateThread)
{
// Dark Souls 3
if (GetProcId(m_ds3Name) == 0)
m_mainFrame->MenuItemEnable(false, menuItem::DarkSouls3);
else
m_mainFrame->MenuItemEnable(true, menuItem::DarkSouls3);
// Need for Speed: Most Wanted
if (GetProcId(m_nfsmwName) == 0)
m_mainFrame->MenuItemEnable(false, menuItem::NFSMostWanted);
else
m_mainFrame->MenuItemEnable(true, menuItem::NFSMostWanted);
// Serious Sam: The Second Encounter
if (GetProcId(m_sstseName) == 0)
m_mainFrame->MenuItemEnable(false, menuItem::SeriousSamTSE);
else
m_mainFrame->MenuItemEnable(true, menuItem::SeriousSamTSE);
// Sleep 1.5s to save resources
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
}
// set the promise that the thread has ended execution
barrier.set_value();
}
edit:
The program terminates after ~cApp. Therefor i think that in this particular case i do not have to delete all of that memory because the os takes care of it.
edit2:
C2893: Failed to specialize function template
"unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...)
noexcept()".
C2780: "unknown-type std::invoke(_Callable &&) noexcept()":
expects 1 arguments - 2 provided
C2672: "invoke": no matching overloaded function found
m_tCheckProcList = new std::thread(&cApp::CheckProcessList, std::move(barrier));
I don't know to which lines your errors pertains (you didn't show this) but I suspect at least above statement is wrong.
If you pass an address of a thread procedure to std::thread constructor and this procedure is a non-static member function the next argument after must be an address of the object you refer to (after all a non-static member function must have an instance that it is called on behalf of). std::promise is not a type which contains such a function pointer type &cApp::CheckProcessList so this cannot work.
If you want to associate that thread with the object that creates it typically such invocation looks like:
std::thread(&cApp::CheckProcessList, this, ...
Or one can use either a static member function or a free function.
cApp::CheckProcessList(std::promise<void> barrier)
Another problem in your code is passing a promise object by value to the thread function. This means a local copy of the promise but promise is not copyable.
You also can't pass it either by reference or by pointer! because barrier is a local variable of OnInit() method and as soon as that method finishes that variable gets destroyed anyway - the underlying detached thread will mess around with invalid stackframe or cause undefined behavior of any kind. Perhaps you could make the barrier a data member or rethink your design.
Be very cautious while dealing with detached threads. They are full of pitfalls when used improperly.
class ThreadOne {
public:
ThreadOne();
void RealThread();
void EnqueueJob(s_info job);
std::queue<s_info> q_jobs;
private:
H5::H5File* targetFile = new H5::H5File("file.h5", H5F_ACC_TRUNC);
std::condition_variable cv_condition;
std::mutex m_job_q_;
};
ThreadOne::ThreadOne() {
}
void ThreadOne::RealThread() {
while (true) {
std::unique_lock<std::mutex> lock(m_job_q_);
cv_condition.wait(lock, [this]() { return !this->q_jobs.empty(); });
s_info info = std::move(q_jobs.front());
q_jobs.pop();
lock.unlock();
//* DO THE JOB *//
}
}
void ThreadOne::EnqueueJob(s_info job) {
{
std::lock_guard<std::mutex> lock(m_job_q_);
q_jobs.push(std::move(job));
}
cv_condition.notify_one();
}
ThreadOne *tWrite = new ThreadOne();
I want to make a thread and send it a pointer of an array and its name as a struct(s_info), and then make the thread write it into a file. I think that it's better than creating a thread whenever writing is needed.
I could make a thread pool and allocate jobs to it, but it's not allowed to write the same file concurrently in my situation, I think that just making a thread will be enough and the program will still do CPU-bound jobs when writing job is in process.
To sum up, this class (hopefully) gets array pointers and their dataset names, puts them in q_jobs and RealThread writes the arrays into a file.
I referred to a C++ thread pool program and the program initiates threads like this:
std::vector<std::thread> vec_worker_threads;
vector_worker_threads.reserve(num_threads_);
vector_worker_threads.emplace_back([this]() { this->RealThread(); });
I'm new to C++ and I understand what the code above does, but I don't know how to initiate RealThread in my class without a vector. How can I make an instance of the class that has a thread(RealThread) that's already ready inside it?
From what I can gather, and as already discussed in the comments, you simply want a std::thread member for ThreadOne:
class ThreadOne {
std::thread thread;
public:
~ThreadOne();
//...
};
//...
ThreadOne::ThreadOne() {
thread = std::thread{RealThread, this};
}
ThreadOne::~ThreadOne() {
// (potentially) notify thread to finish first
if(thread.joinable())
thread.join();
}
//...
ThreadOne tWrite;
Note that I did not start the thread in the member-initializer-list of the constructor in order to avoid the thread accessing other members that have not been initialized yet. (The default constructor of std::thread does not start any thread.)
I also wrote a destructor which will wait for the thread to finish and join it. You must always join threads before destroying the std::thread object attached to it, otherwise your program will call std::terminate and abort.
Finally, I replaced tWrite from being a pointer to being a class type directly. There is probably no reason for you to use dynamic allocation there and even if you have a need for it, you should be using
auto tWrite = std::make_unique<ThreadOne>();
or equivalent, instead, so that you are not going to rely on manually deleteing the pointer at the correct place.
Also note that your current RealThread function seems to never finish. It must return at some point, probably after receiving a notification from the main thread, otherwise thread.join() will wait forever.
I am working on a project where I will be ingesting multiple binary files, decode them, and convert their data into a CSV. I figured the quickest way to do this would be to thread the work. Simply load the files into a queue, have the threads grab a file, work on it, convert it, output it, and then die.
What I wrote actually works great, however, I cannot figure out how to get the GUI to be responsive as I have a progress bar that I would like to update or simply have the user move the GUI to a corner while it processes the data. And I believe this is because std::thread is just hanging up the GUI.
In my code I have the following function once a button is pressed to execute:
void MyExtractor::on_Execute_clicked()
{
QStringList binary = tlmFiles.entryList(QStringList() << "*.bin",QDir::Files);
queue.clear();
threadPool.clear();
if(binary.size() != 0)
{
foreach(QString filename, binary)
{
queue.emplace_back(inputDir + '/' + filename);
}
for (unsigned int i = 0; i < std::thread::hardware_concurrency(); ++i)
{
threadPool.emplace_back(&MyExtractor::initThread,this,std::ref(queue),std::ref(mut));
}
}
else
{
message.setText("No binary files found! Please select another folder!");
message.exec();
}
for (auto &&e : threadPool)
{
e.join();
}
}
And initThread looks like this:
void MyExtractor::initThread(std::deque<QString> &queue, std::mutex &mutex)
{
QString file;
QString toOutput = outputDir;
while(queue.size() > 0)
{
{
std::lock_guard<std::mutex> lock(mutex);
if(!queue.empty())
{
file = queue.front();
queue.pop_front();
}
}
BitExtract *bitExtractor = new BitExtract();
if(file.size() != 0)
{
bitExtractor->extract(file,toOutput);
}
delete bitExtractor;
}
}
I have been reading about QThreads. And from what I think I have been reading, it seems I need to create a separate thread to watch the work, and the other thread to watch the GUI? I am not sure if I have worded that correctly. However, I am not even sure how to go about that since I am using a std::thread to do the conversion, and I am not sure how well QThread will play with this. Any suggestions?
EDIT: I should make it clear that threadPool is a std::vector<std::thread>
As noted by #drescherjm, your problem is here:
for (auto &&e : threadPool)
{
e.join();
}
join() won't return until the thread has completed, which means your GUI thread will be blocked inside that for-loop until all threads have exited, which is what you want to avoid. (it's always desirable for any function in the main/Qt/GUI thread to return as quickly as possible, so that Qt's GUI event loop can remain responsive)
Avoiding that is fairly straightforward -- instead of calling join() right after the threads have been spawned, you should only call join() on a thread after the thread has notified you that it has completed its work and is about to exit. That way join() will never take more than a few milliseconds to return.
As for how to get a std::thread to notify your main/GUI thread that it has finished its task, one simple way to do it is to have your std::thread call QApplication::postEvent() just before it exits, and override the event(QEvent *) virtual method on (whatever object you passed in as the first argument to postEvent()) to handle the posted event-object (note that you can make your own subclass of QEvent that contains whatever data you want to send to the GUI thread) by calling join() on the std::thread, plus whatever cleanup and result-handling code you need to execute after a thread has returned its result.
Maybe there is a really simple solution for my problem, but I'm really confused with all the boosts around me.
Here's my problem:
I want to start a task (calculation, file system operations, etc.), raised by a callback system which calls the CallbackReceived function and I want to pass this operation to a thread, typically represented by a member function of an object. The thread isn't guaranteed to finish, so it should have something to cancel it after some time.
Something like (don't know if this is 100% correct):
// ...
MyObject object;
// ...
void CallbackReceived(int parameter) {
boost::thread tThread(&MyObject::calculate, *&object);
boost::asio::deadline_timer tDeadlineTimer(_ioService, boost::posix_time::seconds(2));
tDeadlineTimer.async_wait(boost::bind(DeadlineTimeOut, boost::asio::placeholders::error));
tThread.join();
}
Basically, a tThread.join()` waits for the return of the thread. While waiting, my main could not receive any callbacks that may come in because it's blocked and sleeps.
So what can one do, to run the thread and not to block the calling initial program while executing the operation?
You can call join just when you need the result of the calculations.
Something like "Future" pattern. Anyway, you would have to make your thread variable global to the CallBackRecieved function (You can write some wrapper).
Note: you can call join, when thread finished its' work - nothing will be blocked.
What do you want to do with the result of calculate?
Your main thread is blocked in the .join().
If you want to handle other callbacks, you have to return to the normal execution flow, waiting for another call.
Then you have to ask yourself what do you do with the result of calculate when it's finished. Maybe the thread can put the result in a shared resource somewhere and finish gracefully.
You must first sort out all what your code is supposed to do ( processing callbacks, starting threads, what to do with the result ) then you can think of implementing it. There are new constructs in boost and C++11 called promise and future that could suit you but first you have to think about what you want.
Actually you could call the callback while your main thread is sleeping. It would just run on the context (stack) of your thread.
You probably don't want to call join at the point you are at but later or never.
Example (pseudocode):
class Worker {
void doWork(void * mainthread){
Main* main = static_cast<Main*>(mainthread);
while(hasWorkTodo){
//work
//inform main
main->callbackwithinformation(information);
}
}
class Main{
atomi_int filesfound;
void main_part(){
//start worker
boost::thread thread(&Worker::doWork, &object, this);
while(hasworktodo){
//do work
//use filesfound here
}
//About to finish make sure we join our thread
thread.join();
}
void callbackwithinformation(int updatedcount){
//here we set a flag or pass some object
//probably will need an atomic operation
filesfound = updatedcount;
}
}
You would define the implementations in cpp and the interface in a h file so no circular dependency would arise, since you are only using Main as a argument in the interface a forward declaration would suffice.
//worker.h
class mainthread;
class Worker {
void doWork(void * mainthread);
}
//worker.cpp
#include "main.h"
void Worker::doWork(/* and so on*/}
//main.h
class Main{
atomi_int filesfound;
void main_part();
void callbackwithinformation(int updatedcount);
}
//main.cpp
//no need for worker.h here
void Main::main_part() /* implementation and so on */
I'm using a QThread and inside its run method I have a timer invoking a function that performs some heavy actions that take some time. Usually more than the interval that triggers the timer (but not always).
What I need is to protect this method so it can be invoked only if it has completed its previous job.
Here is the code:
NotificationThread::NotificationThread(QObject *parent)
: QThread(parent),
bWorking(false),
m_timerInterval(0)
{
}
NotificationThread::~NotificationThread()
{
;
}
void NotificationThread::fire()
{
if (!bWorking)
{
m_mutex.lock(); // <-- This is not protection the GetUpdateTime method from invoking over and over.
bWorking = true;
int size = groupsMarkedForUpdate.size();
if (MyApp::getInstance()->GetUpdateTime(batchVectorResult))
{
bWorking = false;
emit UpdateNotifications();
}
m_mutex.unlock();
}
}
void NotificationThread::run()
{
m_NotificationTimer = new QTimer();
connect(m_NotificationTimer,
SIGNAL(timeout()),
this,
SLOT(fire(),
Qt::DirectConnection));
int interval = val.toInt();
m_NotificationTimer->setInterval(3000);
m_NotificationTimer->start();
QThread::exec();
}
// This method is invoked from the main class
void NotificationThread::Execute(const QStringList batchReqList)
{
m_batchReqList = batchReqList;
start();
}
You could always have a thread that needs to run the method connected to an onDone signal that alerts all subscribers that it is complete. Then you should not run into the problems associated with double lock check and memory reordering. Maintain the run state in each thread.
I'm assuming you want to protect your thread from calls from another thread. Am I right? If yes, then..
This is what QMutex is for. QMutex gives you an interface to "lock" the thread until it is "unlocked", thus serializing access to the thread. You can choose to unlock the thread until it is done doing its work. But use it at your own risk. QMutex presents its own problems when used incorrectly. Refer to the documentation for more information on this.
But there are many more ways to solve your problem, like for example, #Beached suggests a simpler way to solve the problem; your instance of QThread would emit a signal if it's done. Or better yet, make a bool isDone inside your thread which would then be true if it's done, or false if it's not. If ever it's true then it's safe to call the method. But make sure you do not manipulate isDone outside the thread that owns it. I suggest you only manipulate isDone inside your QThread.
Here's the class documentation: link
LOL, I seriously misinterpreted your question. Sorry. It seems you've already done my second suggestion with bWorking.