Search code examples
c++multithreadingvisual-studio-2010wxwidgets

wxwidgets - exit the thread the right way


I run openCL /openGL program which uses wxWidget as gui enviroment

Inside object of class ,which derives from wxThread,I perform some complicated calculations and build many openCL programs. I want to delete the thread .But the thread is not deleted immediately – it continue to build programs and just after it finishes with all the compilations.

I know that I can use wxThread::KIll() to exit the thread but it cause some memory problems so its not really an option.

I have myFrame class which is derived from wxFrame.it has pCanvas pointer ,which points to the object which is derived from wxCanvas *pCanvas object includes the myThread (which runs the complicated calculation)

void myFrame::onExit(wxCommandEvent& WXUNUSED(event))
{
       if(_pCanvas != NULL )
       {
              wxCriticalSectionLocker enter(_smokeThreadCS);
              // smoke thread still exists
              if (_pCanvas->getThread() != NULL)
              {
                     //_pCanvas->getSmokeThread()->Delete(); <-waits until thread ends and after it application terminates
                     _pCanvas->getSmokeThread()->Kill();     <- immediately makes the application not responding
              }
       }
       // exit from the critical section to give the thread
       // the possibility to enter its destructor
       // (which is guarded with m_pThreadCS critical section!)

       while (true)
       {
              { // was the ~MyThread() function executed?
                     wxCriticalSectionLocker enter(_smokeThreadCS);
                     if (!_pCanvas->getSmokeThread()) break;
              }

              // wait for thread completion
              wxThread::This()->Sleep(1);
       }
       DestroyChildren();
       Destroy();
       // Close the main frame, this ends the application run:
       Close(true);
}

Solution

  • Killing a thread like that is indeed very bad. It's best to give the thread a chance to clean up.

    Graceful thread termination is usually done by periodically checking a flag that tells it to exit:

    volatile bool continue_processing = true;
    thread thread;
    
    void compile_thread()
    {
        while(continue_processing)
        {
            // compile one OpenCL program.
        }
    }
    
    void terminate()
    {
        read_write_barrier();
        continue_processing = false;
        write_barrier();
    
        thread.join(); // wait for thread to exit itself.
    }
    

    Depending on your CPU and compiler, simply marking continue_processing as volatile might not be enough to make the change happen immediately and visible to the other thread, so barriers are used.

    You'll have to consult your compiler's documentation to see how to create a barrier... they're different in each one. VC++ uses _ReadWriteBarrier() and _WriteBarrier().