From: Mattia B. <mat...@li...> - 2006-08-03 18:14:23
|
Hi all, the topic is abviously threads. This program: ========== #!/usr/bin/perl -w use strict; use warnings; use threads; use Test::More tests => 4; use Wx; my $app = Wx::App->new( sub { 1 } ); my $color = Wx::Colour->new( 0, 10, 20 ); use Devel::Peek; my $t = threads->create ( sub { ok( 1, 'In thread' ); } ); ok( 1, 'Before join' ); $t->join; ok( 1, 'After join' ); END { ok( 1, 'At END' ) }; ========= crashes after test 3 (after join). The reason is that when the thread is started the perl-space variables are cloned, but the C++-space objects are not, so bot threads think they hold the last reference to $color, both try to free the underlying C++ object => segmentation fault. There are various way to work around this; all involve keeping tracks of created objects (Wx::Colour instances in this case) and doing something special at clone time. This solves the problem once you decide what special action you want to take. Options: 1 - the new thread is denied access to the parent thread objects (tried and works; you should not access wxThings from multiple threads anyway) 2 - clone the C++ instances; for each variable do (more or less) $var = Wx::Colour->new( $var ); 3 - give the new thread access to the original thread's C++ objects avoiding the double free (i.e. do what happens now, except for the segfault). 4 - other options? Any suggestions? Thanks! Mattia The list of classes needing special treatment is: Wx::DataObject Wx::DropTarget Wx::FileSystem Wx::FSFile Wx::GridCellAttr Wx::GridCellAttr Wx::GridCellEditor Wx::GridCellRenderer Wx::HtmlEasyPrinting Wx::Printer Wx::XmlResource Wx::Accelerators Wx::Bitmap Wx::Brush Wx::Cursor Wx::Font Wx::Icon Wx::Image Wx::ImageList Wx::Locale Wx::Palette Wx::Pen |
From: Dan S. <da...@si...> - 2006-08-05 01:11:29
|
At 8:18 PM +0200 8/3/06, Mattia Barbon wrote: > There are various way to work around this; all involve keeping tracks >of created objects (Wx::Colour instances in this case) and doing something >special at clone time. This solves the problem once you decide what >special action you want to take. > > Options: >1 - the new thread is denied access to the parent thread objects > (tried and works; you should not access wxThings from multiple > threads anyway) This would be the best option -- many GUIs don't like multiple threads issuing gui requests. (IIRC various versions of Windows and OS X have had this issue in the past, though I don't know about now) -- Dan --------------------------------------it's like this------------------- Dan Sugalski even samurai da...@si... have teddy bears and even teddy bears get drunk |
From: Mark D. <mar...@zn...> - 2006-08-07 23:26:57
|
Hi, I think 2 - cloning the C++ objects is probably just about the best option. I can imagine the possibility of a situation where it might be of some use for a thread to get a copy of a parent object and go to work on that in the background. Having said that, I would not choose 2 if that option represented much more work than 1 or 3. As there's no clear obvious choice, I think whichever option is easiest for you to implement. I assume we are only concerned with the listed object types and that with any of the options, the following code in a secondary thread would still work (I'm concerned about using Wx::Window::FindWindowById in the context shown below) my $WINDOW_ID = (the ID of a window in my main gui thread); my $window = Wx::Window::FindWindowById($WINDOW_ID, undef); my $newevent = Wx::PlThreadEvent->new( -1, $MY_EVENT_ID, $sharedvar ); Wx::PostEvent( $window, $newevent ); Regards Mark Mattia Barbon wrote: > Hi all, > the topic is abviously threads. This program: > > ========== > #!/usr/bin/perl -w > > use strict; > use warnings; > use threads; > use Test::More tests => 4; > > use Wx; > > my $app = Wx::App->new( sub { 1 } ); > my $color = Wx::Colour->new( 0, 10, 20 ); > > use Devel::Peek; > > my $t = threads->create > ( sub { > ok( 1, 'In thread' ); > } ); > ok( 1, 'Before join' ); > $t->join; > ok( 1, 'After join' ); > > END { ok( 1, 'At END' ) }; > ========= > > crashes after test 3 (after join). The reason is that when the thread is > started the perl-space variables are cloned, but the C++-space objects > are not, so bot threads think they hold the last reference to $color, > both try to free the underlying C++ object => segmentation fault. > > There are various way to work around this; all involve keeping tracks > of created objects (Wx::Colour instances in this case) and doing something > special at clone time. This solves the problem once you decide what > special action you want to take. > > Options: > 1 - the new thread is denied access to the parent thread objects > (tried and works; you should not access wxThings from multiple > threads anyway) > 2 - clone the C++ instances; for each variable do (more or less) > $var = Wx::Colour->new( $var ); > 3 - give the new thread access to the original thread's C++ objects > avoiding the double free (i.e. do what happens now, except for the > segfault). > 4 - other options? > > Any suggestions? > > Thanks! > Mattia > > The list of classes needing special treatment is: > Wx::DataObject > Wx::DropTarget > Wx::FileSystem > Wx::FSFile > Wx::GridCellAttr > Wx::GridCellAttr > Wx::GridCellEditor > Wx::GridCellRenderer > Wx::HtmlEasyPrinting > Wx::Printer > Wx::XmlResource > Wx::Accelerators > Wx::Bitmap > Wx::Brush > Wx::Cursor > Wx::Font > Wx::Icon > Wx::Image > Wx::ImageList > Wx::Locale > Wx::Palette > Wx::Pen > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys -- and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > wxperl-users mailing list > wxp...@li... > https://lists.sourceforge.net/lists/listinfo/wxperl-users |
From: Mattia B. <mat...@li...> - 2006-08-11 20:37:32
|
On Tue, 08 Aug 2006 00:24:38 +0100 Mark Dootson <mar...@zn...> wrote: Hi, > Having said that, I would not choose 2 if that option represented much > more work than 1 or 3. It is somewhat more work, so I went for option 1 (quick and effective). Implementing a different solution is still possible, even for single classes. In addition to that, as Dan notes, some wxWidgets methods internally call functions in the underlying GUI toolkit, so event if the interaction with a cloned object is safe at the C++ level, it might not be at the GUI level, so option 1 is really the safest. > I assume we are only concerned with the listed object types and that Yes. > with any of the options, the following code in a secondary thread would > still work (I'm concerned about using Wx::Window::FindWindowById in the > context shown below) > > my $WINDOW_ID = (the ID of a window in my main gui thread); > my $window = Wx::Window::FindWindowById($WINDOW_ID, undef); > my $newevent = Wx::PlThreadEvent->new( -1, $MY_EVENT_ID, $sharedvar ); > Wx::PostEvent( $window, $newevent ); Well, this is not exactly the case I am discussing, since the objects in this example are not clones of the ones in the main thread; anyway using Wx::PostEvent will most definitely work in any wxPerl/threads scenario. Thanks to you and Dan for your input Mattia |