Delegate task to another thread - Help Topic is solved

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.
User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Delegate task to another thread - Help

Post by evstevemd » Fri Jan 28, 2011 1:34 pm

Hi,
My GUI thread was handling all the database issues and all the stuff. Now I want to delegate some tasks on the background thread. I have previously asked here about thread and I have theoretical knowledge of inheriting from wxThread and implement wxThread::Entry(). But I'm puzzled on how to exchange data btwn threads. I have never done before threads.

Basically each time the thread is dispatched it have to query database and return the resultset from Database (wxSQLite3)

Thanks
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Post by Auria » Fri Jan 28, 2011 2:52 pm

Exchanging data can be done in several ways.

1) Give a copy of the data to the thread when creating it. A copy will avoid all synchronisation problems.
2) Give a pointer to some class to the thread when creating it. Then you need to use mutexes to synchronize accesses to this class since it's not a copy.
3) Use the new message queue class if you use wx 2.9 : http://docs.wxwidgets.org/trunk/classwx ... _01_4.html (especially useful to communicate from the main thread to the thread)
4) To communicate from the thread to the main thread, see : http://wiki.wxwidgets.org/Inter-Thread_ ... ain_thread
"Keyboard not detected. Press F1 to continue"
-- Windows

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jan 28, 2011 3:35 pm

Auria wrote:Exchanging data can be done in several ways.

1) Give a copy of the data to the thread when creating it. A copy will avoid all synchronisation problems.
This seems simple but I don't understand what you mean by giving a copy! I just pass wxString consisting of SQL statement and the thread querries db and returns result to the GUI. So how in such circumstance I apply this method?
Auria wrote: 2) Give a pointer to some class to the thread when creating it. Then you need to use mutexes to synchronize accesses to this class since it's not a copy.
I will try to avoid as much as possible of mutexes. I'm afraid of complicating thing (may be stupid fear!)
Auria wrote: 3) Use the new message queue class if you use wx 2.9 : http://docs.wxwidgets.org/trunk/classwx ... _01_4.html (especially useful to communicate from the main thread to the thread)
This might be another good alternative. I have read Manual, I have not understand it. I'm going to read it again!
Auria wrote: 4) To communicate from the thread to the main thread, see : http://wiki.wxwidgets.org/Inter-Thread_ ... ain_thread
Mh! I have read this many times but I guess in this scenario it will be hard to implement. May be because of my newbeesh in wxThread arena!

Excuse my ignorance :P
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre » Fri Jan 28, 2011 4:57 pm

I just pass wxString consisting of SQL statement and the thread querries db and returns result to the GUI. So how in such circumstance I apply this method?
This way of doing can be non-thread safe... wxString use Copy-On-Write mechanism. So, when you pass a string at creation of the thread, the new copy points to the same data as the original one. When you modify the original one, all the COW mechanism ensures that each instance content is consistent... but this mechanism is not thread-safe. So, in your case, it can be dangerous to perform that. So, just take care when doing this...

Note that you are speaking of echanging data, but there is also the synchronisation problem. I suppose your thread is performing a DB request and that, when it finishes, the GUI thread shall perform corresponding action. In this case, as suggested by Auria, using wxEvents is probably the best approach with wxWidgets, so that the main thread will be informed when the DB request will be finished. Note that creating custom events is not so hard. And posting an event from a working thread to main one is a very simple thing to do...

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jan 28, 2011 5:19 pm

briceandre wrote:
I just pass wxString consisting of SQL statement and the thread querries db and returns result to the GUI. So how in such circumstance I apply this method?
This way of doing can be non-thread safe... wxString use Copy-On-Write mechanism. So, when you pass a string at creation of the thread, the new copy points to the same data as the original one. When you modify the original one, all the COW mechanism ensures that each instance content is consistent... but this mechanism is not thread-safe. So, in your case, it can be dangerous to perform that. So, just take care when doing this...
Isn't wx29 using std:string which are said to be safe? I remember reading somewhere in forum or mailing list of such a thing....not very sure where!
briceandre wrote:Note that you are speaking of echanging data, but there is also the synchronisation problem. I suppose your thread is performing a DB request and that, when it finishes, the GUI thread shall perform corresponding action. In this case, as suggested by Auria, using wxEvents is probably the best approach with wxWidgets, so that the main thread will be informed when the DB request will be finished. Note that creating custom events is not so hard. And posting an event from a working thread to main one is a very simple thing to do...
Mhh would you clarify on that? How do I pass a string to thread and receive resultset using this method? New things looks complicated at first look!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre » Fri Jan 28, 2011 5:55 pm

Isn't wx29 using std:string which are said to be safe?
If you are using wx29, I think you are right : it uses std::string. But I am not sure all STL implementations are thread-safe. So, I would take care, event with this version of wxWidgets.
How do I pass a string to thread and receive resultset using this method?
You create a thread to which you provide the SQL request to perform. The thread implements the request in the Entry method. At the end of the Entry method, while the result is computed, you send an event that contains the result of the request. So, in the main thread, all you have to do is connect an event hanlder, exactly like you connect an event handler to a button click, or something like that.

The only "difficulty" is that, if you want the event to contain the content of the SQL query, you have to create a custom event. But it's not as complicate as it can seem to be. Take a look at that link : http://wiki.wxwidgets.org/Custom_Events for more information on how to create a custom event.

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jan 28, 2011 6:09 pm

briceandre wrote:
Isn't wx29 using std:string which are said to be safe?
If you are using wx29, I think you are right : it uses std::string. But I am not sure all STL implementations are thread-safe. So, I would take care, event with this version of wxWidgets.
How do I pass a string to thread and receive resultset using this method?
You create a thread to which you provide the SQL request to perform. The thread implements the request in the Entry method. At the end of the Entry method, while the result is computed, you send an event that contains the result of the request. So, in the main thread, all you have to do is connect an event hanlder, exactly like you connect an event handler to a button click, or something like that.

The only "difficulty" is that, if you want the event to contain the content of the SQL query, you have to create a custom event. But it's not as complicate as it can seem to be. Take a look at that link : http://wiki.wxwidgets.org/Custom_Events for more information on how to create a custom event.
Let me read the Links and do what you suggested here. Since you propose take care even with wx29, what do you suggest I do?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre » Fri Jan 28, 2011 6:29 pm

With wxWidgets, there is no way to ensure that a deep copy is performed, when COW mechanism is used. But there are workarounds to ensure this. If you write something like this, no deep-copy is performed if COW is implemented :

Code: Select all

wxString copy = original_str;
But, if you write something like that, you should not encounter any problem:

Code: Select all

wxString copy = wxString::Format("%s", original_str.c_str());
Another way would be to avoid using wxStrings in data shared from one thread to the other...

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Fri Jan 28, 2011 6:39 pm

briceandre wrote:With wxWidgets, there is no way to ensure that a deep copy is performed, when COW mechanism is used. But there are workarounds to ensure this. If you write something like this, no deep-copy is performed if COW is implemented :

Code: Select all

wxString copy = original_str;
But, if you write something like that, you should not encounter any problem:

Code: Select all

wxString copy = wxString::Format("%s", original_str.c_str());
Another way would be to avoid using wxStrings in data shared from one thread to the other...
I will use that! Thanks!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

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

Post by doublemax » Fri Jan 28, 2011 6:47 pm

Just

Code: Select all

wxString copy( original_str.c_str() );
is sufficient.

However, wxString is not the only class which is not thread-safe. When dealing with multiple threads, sooner or later you will have to use mutexes (which is not that hard or complicated).
Use the source, Luke!

briceandre
Ultimate wxWidgets Guru
Ultimate wxWidgets Guru
Posts: 670
Joined: Tue Aug 31, 2010 6:22 am
Location: Belgium

Post by briceandre » Sat Jan 29, 2011 6:12 am

When dealing with multiple threads, sooner or later you will have to use mutexes (which is not that hard or complicated).
I agree with you. But mutexes will not solve all problems :

Code: Select all

mutex.Lock();
wxString copy_str = base_str;
mutex.Unlock();
does not solve the problem of reference counting.

Code: Select all

wxString copy( original_str.c_str() );
Your solution effectively works, and is simplier than mine. I will probably use yours in future. But may I insist that it only works if people use the .c_str() in copied string. If ommited, COW is used. In other words, the following code is still erroneous (in mutli-thread context):

Code: Select all

wxString copy( original_str);

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Sat Jan 29, 2011 8:55 am

thanks buddies, I really appreciate your posts. Let me code something and I will let it open for a while!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

jfouche
Super wx Problem Solver
Super wx Problem Solver
Posts: 442
Joined: Tue May 06, 2008 4:52 pm
Location: France

Post by jfouche » Sat Jan 29, 2011 9:16 am

IIRC, wxThreadEvent is usefull for what you want (it deep copy the string).[/url]
Jérémie

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Sat Jan 29, 2011 11:49 am

jfouche wrote:IIRC, wxThreadEvent is usefull for what you want (it deep copy the string).[/url]
Thanks Jeremie, I will have a look at it. It sounds good!
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2292
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Post by evstevemd » Sat Jan 29, 2011 11:54 am

jfouche wrote:IIRC, wxThreadEvent is usefull for what you want (it deep copy the string).[/url]
I'm interested in this function
void wxThreadEvent::SetPayload ( const T & payload ) [inline]

Sets custom data payload.

The payload argument may be of any type that wxAny can handle (i.e. pretty much anything). Note that T's copy constructor must be thread-safe, i.e. create a copy that doesn't share anything with the original (see Clone()).
does wxAny handle resultsets from wxSQLite3?
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

Post Reply