|
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 |