Wiggins has asked for the wisdom of the Perl Monks concerning the following question:

Having passed through the Novice gates of threads, PerlTk, and shared hashes, I find myself in the past in failure.

Having completed my threaded Perl, I now attempted to move it to the destination system. That is, from Knoppix (Perl 5.8.8) to RHEL4 WS (Perl 5.8.5). BOOM!

... use threads (); use threads::shared (); use Thread::Semaphore; ... my $line_semi :shared = new Thread::Semaphore(0); #works in 5.8.8 ... ... sub sendout_sub ($ $) { ... { $line_semi->down(1); # line 309 lock @xlines; $line = shift @xlines; } #implicit unlock; ....

The error in 5.8.5 is:

"Thread failed to start: Can't call method "down" on unblessed reference at line 309."

Did ::Semaphore do the creation of the returned reference incorrectly?

Can I do my own blessing into Semaphore?

Upgrading Thread::Semaphore looks like a complete upgrading to 5.8.8. That would be a politically hard task to get done.

Replies are listed 'Best First'.
Re: I lost my "bless"ing.
by jettero (Monsignor) on Dec 20, 2006 at 21:15 UTC

    Hrm, threads::shared seems to state that "bless is not supported on shared references." That's probably the biggest problem here. It's listed as a bug (at the bottom) but indicates that if you hold out it "is expected to be implemented in a future version of Perl."

    -Paul

      But what use is a semaphore that is not shared? Like one hand clapping?
      Maybe the "shared" part is builtin.?
      So was it possible to use ::Semaphore in 5.8.5; and if so, how was it tested, if not shared between threads?

      Probably an imponderable of a misty past.

        This may be of interest... it's source from the Semaphore.pm:

        sub new { my $class = shift; my $val : shared = @_ ? shift : 1; bless \$val, $class; }

        It says that you don't need to share it because it's already shared. Also, note that the author shares the scalar and then blesses it... Not the other way around.

        Use the source Luke.

        -Paul

Re: I lost my "bless"ing.
by ikegami (Patriarch) on Dec 20, 2006 at 23:00 UTC

    If you call down and up as functions rather than methods, you can avoid the need to share a reference.

    use Thread::Semaphore qw( ); use threads::shared qw( ); BEGIN { *sema_down = \&Thread::Semaphore::down; *sema_up = \&Thread::Semaphore::up; } my $line_semi : shared = 0; ... sema_down(\$line_semi, 1); ... sema_up(\$line_semi, 1);

    Update: Alternatively:

    use Thread::Semaphore qw( ); use threads::shared qw( is_shared ); BEGIN { package Thread::Semaphore; no warnings 'redefine'; sub new { my $class = shift; if (@_ && is_shared($_[0])) { return bless \$_[0], $class; } else { my $val : shared = @_ ? shift : 1; return bless \$val, $class; } } } my $line_semi_count : shared = 0; my $line_semi = Thread::Semaphore->new($line_semi_count); ... $line_semi->down(1); ... $line_semi->up(1);

    Both methods are backwards compatible.

      Great answer. I am using method #1. On this vanilla RH installation, threads::shared does not have an "is_shared" service.

      Thanks again.

Re: I lost my "bless"ing.
by diotalevi (Canon) on Dec 20, 2006 at 22:05 UTC

    It's also possible that your 'new' call could be going horribly awry. The syntax reading new Class is horribly buggy and you should never do that in perl. Always do Class->new instead.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: I lost my "bless"ing.
by zentara (Cardinal) on Dec 21, 2006 at 16:26 UTC