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

Hi monks,
Lets say we have a module for message handling to which we pass a callback, and we want to asbtract the user from thread management.
We have all covered except the variables used or declared inside the callback, the user has defined his callback and passed to the module and of course he is expecting to see those variables change, but they won't.
Any hint on doing this? Perhaps is possible to know the local vars inside a function once you have the pointer and share them dymanically? In that case we won't have acess from the callback to previous vars ....
Any hint.
Thanks

Replies are listed 'Best First'.
Re: Thread-safe modules and callbacks
by BrowserUk (Patriarch) on May 09, 2008 at 21:52 UTC

    For my part at least, you are going to have to clarify this question. I cannot make head nor tail of what you are describing.

    My suggestion would be to post some code (a small, working example) to demonstrate what you are doing. And then show the limitation you are encountering that you need to work around.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Ok, lets see the client:
      my $MsgListener = new Msg::Server(2222,\&messageHandler); $MSGListener->Start(); sub messageHandler{ my $message = shift; my $peer = shift; chomp($message); print "MSG from $peer -> $message\n"; my @tokens = split(' ',$message); my $token }
      The server just redirects messages to the callback and the callback gets executed on the message thread so we don't share variables unless we specifically share them, but we want to abstract the user from the threads, I'm not sure if it is possible at all.

        It depends upon what you're trying to achieve.

        1. If you just want the variables to be accessible by the handler using them, then using closures are the simplest option:
          { my $n = 0; sub handler { my $tid = threads->self->tid; for( 1 .. 5e5 ) { usleep( 100 ); print "$tid: ", $n++; } } }

          Each handler will get it's own copy of $n above and can use it without concerns for locking or sharing. It retains it's value across calls to the handler.

        2. If you need to share the data either between the handlers, or between each handler and the main thread, then that requires the data be shared. And that comes with the inherent need for locking.

          Isolating your users from the requirements of shared data is possible, but distinctly non-trivial.

          I am reluctant to expend energy describing possible approached until I:

          1. know that's what you want.
          2. impose upon you for a more complete description of the types of data and uses to which you envisage it will be put.

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Thread-safe modules and callbacks
by pc88mxer (Vicar) on May 09, 2008 at 23:16 UTC
    Are you talking about a callback function that needs to keep track of some state, as in this example:
    our $count = 0; sub my_callback { warn "I've been called ".(++$count)." times\n"; ... } my $thread = threads->create(..., \&my_callback); $thread->join; print "count = $count\n"; # prints 0
    And the issue that this won't work in a threaded-environment because the $count that gets updated is only accessible in one thread (since it is not declared as shared.) So, callbacks have to be thread-aware if they are going to be used in a threaded environment.

    Interesting problem...

      Exactly that! Don't know if possible, it may be possible to access local variables of a function and that could let us delcare as shared dynamically callbacks variables. but that doesn't solve the problem when callback acess main threads variables.
        How about switching to objects, and create a closure for your callback:
        use threads::shared; my $obj = bless {}, 'foo'; sub foo::callback { warn "I've been called ".++($_[0]->{count})." times\n"; } share($obj); # only needed in a threaded environment my $thread = threads->create('start_thread', sub { $obj->callback(@_) +} ); $thread->join; print "count = ", $obj->{count}, "\n"; # prints 3 sub start_thread { my $cb = shift; for (1..3) { $cb->() } }
        Is there a way to implement function call behavior for a blessed reference? If so, you could have the best of both worlds.
Re: Thread-safe modules and callbacks
by Joost (Canon) on May 09, 2008 at 22:07 UTC
Re: Thread-safe modules and callbacks
by zentara (Cardinal) on May 10, 2008 at 12:50 UTC