OK to use Delete and TestDestroy with a Joinable thread?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Virchanza
Experienced Solver
Experienced Solver
Posts: 78
Joined: Sun Jul 19, 2009 6:12 am

OK to use Delete and TestDestroy with a Joinable thread?

Post by Virchanza » Wed Jun 16, 2010 1:47 pm

I know you can use the Delete method and the TestDestroy method with a Detached thread, but I want to ask if it's OK to used these methods on a Joinable thread?

From my main thread, I want to use the Delete method to signal to the secondary thread that I want it to terminate. I will then use the Wait method to wait for the secondary thread to terminate.

Within the secondary thread, I will do some processing and periodically make calls to TestDestroy.

Here's an example. The code in the main thread will be:

Code: Select all

void OnButtonClick_EndSecondaryThread(wxCommandEvent &event)
{
    p_thread->Delete();
    p_thread->Wait();
    delete p_thread;
    p_thread = 0;
}
And there's the code for the secondary thread:

Code: Select all

void *Entry()
{
    while ( !this->TestDestroy() )
    {
        /* Do some processing */
    }
}
Is this OK?

Virchanza
Experienced Solver
Experienced Solver
Posts: 78
Joined: Sun Jul 19, 2009 6:12 am

Post by Virchanza » Thu Jun 17, 2010 9:56 am

Anyone?

I see the following in the wxWidgets manual:

Code: Select all

wxThread::Delete

wxThreadError Delete()

Calling Delete gracefully terminates a detached thread, either when the thread calls TestDestroy or finished processing.

(Note that while this could work on a joinable thread you simply should not call this routine on one as afterwards you may not be able to call wxThread::Wait to free the memory of that thread).
I don't know what to take from it though.

Can you use Delete and TestDestroy with a Joinable thread in a manner I suggested in my original post in this thread?

User avatar
doublemax
Moderator
Moderator
Posts: 15849
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Thu Jun 17, 2010 1:20 pm

Can you use Delete and TestDestroy with a Joinable thread in a manner I suggested in my original post in this thread?
I never used joinable threads (and probably never will, i can hardly find a scenario where they're useful), but as i understand the documentation: No.

Use TestDestroy() and Wait() on joinable threads.

From the docs:
As mentioned, wxThread::Wait or wxThread::Delete attempts to gracefully terminate a joinable and detached thread, respectively. It does this by waiting until the thread in question calls wxThread::TestDestroy or ends processing (returns from wxThread::Entry).
Use the source, Luke!

TrV
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 630
Joined: Wed Jul 04, 2007 1:12 pm

Post by TrV » Thu Jun 17, 2010 3:40 pm

I've also never used joinable threads... however i think Wait() is used for joinable threads in the same manner as Delete() is for detached ones.

Virchanza
Experienced Solver
Experienced Solver
Posts: 78
Joined: Sun Jul 19, 2009 6:12 am

Post by Virchanza » Sat Jun 19, 2010 8:58 am

I too thought that you were supposed to use TestDestroy with Wait, but I've tried it out and it doesn't work.

After I invoke the Wait method from within the Main Thread, the secondary thread's calls to TestDestroy still return false.

Here's how my code works. Firstly, here's the code for the secondary thread:

Code: Select all

class Class_For_Secondary_Joinable_Thread : public wxThread {

public:



    Class_For_Secondary_Joinable_Thread() : wxThread(wxTHREAD_JOINABLE) {}



    void *Entry()

    {
        while ( !this->TestDestroy() )
        {

            /* Keep looping */
        }



        this->Sleep(5000);

    }

};
The idea here is that when the Main Thread invokes the Wait method on the secondary thread, the secondary thread will stall for 5 seconds before ending.

Here's the code in the Main Thread:

Code: Select all

void Race_GUIMain::OnButton1( wxCommandEvent& event )

{

    this->Disable();  /* Freeze the GUI */


    p_secondary_joinable_thread->Wait(); /* This function takes 5 seconds to return! */


    this->Enable();
  /* Unfreeze the GUI */


    m_button2->Enable(false);
  /* Disable a specific button */
}
This code simply does not work. The Wait method never returns because the TestDestroy method continues to return false every time.

I have a workaround for this whereby I use a global variable along with a critical section, but I was hoping I could simply use the Delete method.

Here's how I currently achieve my goal. First I have a class as follows:

Code: Select all

class CriticalSectionLocker_WaitingIndicator {
protected:

    static wxCriticalSection cs;
    static bool is_waiting;

public:

    CriticalSectionLocker_WaitingIndicator() { cs.Enter(); }

    ~CriticalSectionLocker_WaitingIndicator() { cs.Leave(); }



    void Set_As_Waiting()

    {

        is_waiting = true;

    }

    bool Test_Is_Waiting_And_Reset()

    {

        if ( is_waiting )

        {

            is_waiting = false;

            return true;

        }



        return false;

    }
};
Then from within my Main Thread, before I invoke the Wait method on the secondary thread, I do this:

Code: Select all

CriticalSectionLocker_WaitingIndicator().SetAsWaiting();

p_secondary_thread->Wait();
And then within the secondary thread, instead of calling TestDestroy, I do:

Code: Select all


    void *Entry()

    {
        while ( !CriticalSectionLocker_WaitingIndicator().Test_Is_Waiting_And_Reset() )
        {

            /* Keep looping */
        }



        this->Sleep(5000);

    }
This method works but obviously it would be much neater just to use Delete and TestDestroy.

I have actually tried using a combination of Delete, Wait and TestDestroy, and it works fine on wxGTK. However I don't know if what I'm doing is "correct", and I find that the wxWidgets manual is too vague.

User avatar
doublemax
Moderator
Moderator
Posts: 15849
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Post by doublemax » Sat Jun 19, 2010 12:34 pm

It's true that the documentation is not very clear.

After looking into the sources, i can confirm that the combination TestDestroy()/Wait() will not work.

But i'm still not sure if it's ok to use TestDestroy()/Delete() on joinable threads.
If the combination works for you, just leave it that way.

Otherwise or to be on the safe side, use a detached thread instead.
http://docs.wxwidgets.org/stable/wx_wxcondition.html might be useful.
Use the source, Luke!

trivia21
Knows some wx things
Knows some wx things
Posts: 27
Joined: Sun Apr 08, 2012 5:08 pm

Re: OK to use Delete and TestDestroy with a Joinable thread?

Post by trivia21 » Wed May 02, 2012 5:20 pm

Using Destroy then Wait on a joinable thread won't always work. It fails on my system because the thread handle is no longer valid.
Actually I think joinable threads can be useful. I use them for communication over sockets. When the server needs to shut down I prefer closing connections gracefully. On Windows threads are "killed" immediately when the main thread exits, so I need to wait for them to finish. As far as I know there are two options:
1) use a detachable thread, and implement a (redundant) "wait" myself (with wxCondition for example) to avoid waiting for an already destroyed thread
2) use a joinable thread and implement a (redundant) "delete" to be able to use Wait after invoking it (ex. wxCriticalSection + bool).
Am I missing something?

User avatar
doublemax
Moderator
Moderator
Posts: 15849
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: OK to use Delete and TestDestroy with a Joinable thread?

Post by doublemax » Wed May 02, 2012 8:18 pm

1) use a detachable thread, and implement a (redundant) "wait" myself (with wxCondition for example) to avoid waiting for an already destroyed thread
Yes, that's what i do.
Use the source, Luke!

Post Reply