1

I am working on Qt 5.5 and have created a seperate thread that uses 3rd party library APIs. This Api function which when executes consumes all resources and does not allow any other function to execute in that thread.

This new thread starts with a click of button say "Start" and I just do not know how to stop or kill thread when I press stop button. Below is my sample example

threadWorking = new QThread();
 workHeavy    = new WorkingHard; 

        workHeavy->moveToThread( threadWorking );

        connect( threadWorking, SIGNAL( started() ),        workHeavy,     SLOT( slotStartStream() ) );
        connect( workHeavy,     SIGNAL( sigStopStream() ),  threadWorking, SLOT( quit() ) );
        connect( workHeavy,     SIGNAL( sigStopStream() ),  workHeavy,     SLOT(deleteLater() ) );
        connect( threadWorking, SIGNAL( finished() ),       threadWorking, SLOT(deleteLater() ) );

        connect( workHeavy,     SIGNAL( sigStartStream() ), this, SLOT( slotTrueStreamRun()  ) );
        connect( workHeavy,     SIGNAL( sigStopStream() ),  this, SLOT( slotFalseStreamRun() ) );

        connect( this,            SIGNAL( sigMopsCamStopCmd() ), workHeavy, SLOT(slotStopStream() ) );
        threadWorking->start();

Also// void WorkingHard::slotStartStream() 
{
    g_main_loop_run( gloop ); // this consumes all resources.
}
void WorkingHard::slotStopStream() 
{
  // clean up mess
g_main_loop_quit( gloop );
    gst_element_set_state (pipeline, GST_STATE_NULL);
   // g_main_loop_quit( gloop );
    releaseMemory();
}

Please advice me to kill thread based on id or something else. One thing is clear is that I cant go inside thread when function is running.

As folks have suggested to use terminate. If I use terminate() do I still need to free memory as I pointed in fiunction slotStopStream??

samprat
  • 2,150
  • 8
  • 39
  • 73
  • Your sample example is far from complete and minimal, as required. That said, research the term "thread cancellation" and why that is problematic. Using a different process could be an alternative. – Ulrich Eckhardt Feb 03 '16 at 07:34
  • You should show your your `WorkingHard` working loop. That's where you should put the detection for thread termination, but it's hard to advice without knowing what kind of code you have there. – hyde Feb 03 '16 at 07:44
  • As folks have suggested for terminate. If I use terminate() do I still need to free memory as I pointed in function slotStopStream?? – samprat Feb 03 '16 at 09:58
  • Of course if you can make it cleaner by releasing the resources, you should. – Alexander V Feb 03 '16 at 17:01
  • @samprat Thread terminate ends the thread there and then, potentially leaving for example data structures in invalid state. Use it only as a last resort, if you really have no other way to tell the thread to stop with acceptable delay. – hyde Feb 03 '16 at 21:11
  • Can you orphan it? Set some flag to tell it to clean up and terminate itself when it can, set it's priority to the lowest possible, detach it and forget about it? – Martin James Feb 03 '16 at 22:05
  • Can you make it raise an exception that you can catch? Close some fd it's using? Null some data pointer it's using? – Martin James Feb 03 '16 at 22:07

1 Answers1

0

Please advice me to kill thread based on id or something else.

You do not want such advice. Terminating a running thread leaks resources and may well leave your process in a corrupt state - e.g. the heap manager's data structures may be corrupt, or other global state may be corrupt. Do not forcibly terminate threads - anything else is undefined behavior.

I doubt it very much that the g_main_loop_run is "consuming" all resources. Well, it is busy doing something, or is waiting for things to happen. It's an event loop, after all. It's even documented :) Calling g_main_loop_run is not much different from calling exec() on a QEventLoop.

You can call g_main_loop_quit to quit the event loop. If it was QEventLoop, you could call quit on it from any thread. But I'm not sure if g_main_loop_quit is thread-safe, the documentation is mum about it. Alas, we don't have to worry about that: we can invoke it from the worker thread itself.

We'll call g_main_loop_quit from within the loop's context. The lambda's body will run in the worker thread and will cause the loop to exit:

class WorkingHard : public QObject {
   Q_OBJECT
   GMainLoop * gloop;
   ....
};

/// This method is thread-safe
void WorkingHard::quitLoop() {
  auto context = g_main_loop_get_context(gloop);
  g_main_context_invoke(context, +[](gpointer ptr) -> gboolean {
    g_main_loop_quit((GMainLoop*)ptr);
    return FALSE;
  }), (gpointer)gloop);
}

The + operator applied to a lambda converts it to a function pointer. It saves you from defining a stand-alone function.

To end the loop, call quitLoop from any thread.

Note that if you're on Linux, then QEventLoop is based on glib event loop and you can use QEventLoop directly, instead of using GLib apis.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313