AnyEvent with Coro, AKA async TCP daemon.

Andrew Whatson whatson at gmail.com
Mon Aug 5 10:17:38 CEST 2013


Hi Antti,

Ok, yes, if your work is *unavoidably* blocking, then a separate process
is the only real solution.  There are the 'fork_call' and 'run_cmd'
helpers in AnyEvent::Util which can be useful in these situations.

Before resorting to those though, you should investigate whether your
work can be performed asynchronously.  Many operations like database
queries or network communication don't need to actually block, you just
need to wait for them to finish.  Here's an example of doing three
postgres queries simultaneously without forking:

  https://gist.github.com/flatwhatson/6154016

In situations where you're busy doing real work inside some perl
routines, you might want to call 'cede' every now and then so that other
parts of the system don't get blocked (eg. accepting new connections).

Cheers,
Andrew

On Fri, Aug 2, 2013 at 4:15 PM, Antti Linno <sihker at hot.ee> wrote:
> Greetings Andrew
>
> The sleep emulates long running process, most of them are blocking (standard
> postgres queries, datetime calculations etc.) Can I substitute 1000 database
> calls with AnyEvent::sleep?
> Nevermind, grumpy morning :)
> So, is fork my only option for blocking function?
>
> Antti
>
>
> On 08/02/2013 04:59 AM, Andrew Whatson wrote:
>>
>> Hi Antti,
>>
>> You are using a blocking sleep() in your threads, so no work can happen
>> until the sleep completes.  You should use Coro::AnyEvent::sleep()
>> instead, which will allow other threads to run in the interim.
>>
>>   https://metacpan.org/module/Coro::AnyEvent
>>
>> Cheers,
>> Andrew
>>
>> On Thu, Aug 1, 2013 at 11:57 PM, Antti Linno <sihker at hot.ee> wrote:
>>>
>>> Good day.
>>>
>>> I'm trying to build a simple non-blocking TCP daemon. If I need HTTP
>>> daemon,
>>> should I use Twiggy?
>>>
>>> This is what I have so far:
>>>
>>> use Modern::Perl '2012';
>>> use EV;
>>> use AnyEvent::Socket;
>>> use Coro;
>>>
>>> sub start_thread($$$$) {
>>>      my ( $time, $fh, $host, $port ) = @_;
>>>      return async {
>>>          say "Starting sleep of $time, $host, $port";
>>>          sleep $time;
>>>          say "Done sleeping!";
>>>      };
>>> }
>>>
>>> AnyEvent::Socket::tcp_server undef, 11211, sub {
>>>    my ( $fh, $host, $port ) = @_;
>>>
>>>    start_thread 20, $fh, $host, $port;
>>>    }, sub {
>>>    my ( $fh, $thishost, $thisport ) = @_;
>>>    AE::log info => "Bound to $thishost, port $thisport.";
>>>    };
>>>
>>> EV::loop;
>>>
>>> The problem is, this solution is blocking. If I make two requests, then
>>> the
>>> second one is pending, while the first one sleeps.
>>>
>>> I could fork
>>>
>>> sub start_thread($$$$) {
>>>      my ( $time, $fh, $host, $port ) = @_;
>>>      if ( my $pid = fork ) {
>>>          say "Starting sleep of $time, $host, $port";
>>>          sleep 20;
>>>          say "Done sleeping!";
>>>      };
>>> }
>>>
>>> This is not blocking, but is this the optimal way? How to do it with
>>> Coro?
>>>
>>> Greetings,
>>> Antti
>>>
>>> _______________________________________________
>>> anyevent mailing list
>>> anyevent at lists.schmorp.de
>>> http://lists.schmorp.de/mailman/listinfo/anyevent
>
>



More information about the anyevent mailing list