package Coro::LocalScalar; use strict; no strict 'refs'; use Guard; use Carp; use Scalar::Util qw/weaken/; our $VERSION = '0.1'; =head1 NAME Coro::LocalScalar - local() for Coro =head1 ABOUT Perl local() function unuseful for Coro threads. This module uses tie magick to make scalar local for each Coro thread. =head1 SYNOPSIS use Coro; use Coro::LocalScalar; use Coro::EV; my $scalar; Coro::LocalScalar->new->localize($scalar); async { $scalar = "thread 1"; print "1 - $scalar\n"; cede; print "3 - $scalar\n"; cede; print "5 - $scalar\n"; }; async { $scalar = "thread 2"; print "2 - $scalar\n"; cede; print "4 - $scalar\n"; cede; print "6 - $scalar\n"; }; EV::loop; prints 1 - thread 1 2 - thread 2 3 - thread 1 4 - thread 2 5 - thread 1 6 - thread 2 my $obj = Coro::LocalScalar->new; # no tie magick used $obj->value("data"); $obj->value = "data"; my $value = $obj->value; #or my $local_lvalue_closure = $obj->closure; # lvalue coderef $local_lvalue_closure->() = "local data"; # no tie magick used my $testobj = Someclass->new; # attach setter/getter and tied hash element to your object $obj->attach($testobj, 'element_local_in_coros'); $testobj->element_local_in_coros("data"); $testobj->element_local_in_coros = "data"; $testobj->{element_local_in_coros}; # tie magick used =cut sub new { bless {} } sub TIESCALAR {$_[1]}; sub closure { my $self = shift; return sub :lvalue { $self->get; } } sub localize { # tie scalar to container my $self = shift; $self->{scalar} = \$_[0]; weaken $self->{scalar}; # no circular tie($_[0], __PACKAGE__, $self ); $self; } sub attach { # attach setter/getter and tied hash element to class # $container->attach($comeobj, 'db_conn'); $comeobj->{db_conn} and $comeobj->db_conn now local in Coros *{ref($_[1]).'::'.$_[2]} = $_[0]->closure; $_[1]->{$_[2]} = undef unless exists $_[1]->{$_[2]}; $_[0]->localize($_[1]->{$_[2]}); $_[0]; } sub _proto : lvalue { my $self = shift; unless(exists($self->{$Coro::current})){ my $coro = $Coro::current; $self->{$coro} = undef; # init coro data destructor $coro->on_destroy(sub { ${ $self->{scalar} } = undef; # Delete scalar value to prevent unexpected behavior #perl stores values in scalar even if it tied. When Coro::LocalScalar destroys internal value, value stored in scalar still persists although you expected that it would be deleted( and DESTROY called if it`s object) delete $self->{$coro}; undef $coro; }); }; if(@_){ $self->{$Coro::current} = shift } $self->{$Coro::current}; } *STORE = *_proto; sub FETCH : lvalue { shift->{$Coro::current} }; our $AUTOLOAD; sub AUTOLOAD :lvalue { *{$AUTOLOAD} = *_proto; shift->_proto } sub DESTROY {} sub UNTIE {}; 1;