in reply to Re: IO::Async::Loop in multiple modules all loaded
in thread IO::Async::Loop in multiple modules all loaded

I have now created a repository with example code and tests in order to play with websockets and IO::Async::Loop. It is located here/github,

TL;DR: I can have a loop in each module. There does not seem to be a clash when all modules are fetch()ing which means there are instantiated loop object in each fetch() running, not a singleton.. Edit: Totally wrong, there is only one loop, a singleton and this is enforced internally by IO::Async::Loop.

The only tiny problem I found is when fetching (i.e. running each module's fetch()) asynchronously with wait_all of Future. It does not run the last fetch() and it only returns just one result. Of course, the main culprit can be me.

So, if anyone has time and knowledge, to upload the repo and run the tests and offer advice on:

All in all, creating this repository was a good exercise but I am left with the same problems I posted although they do not appear in the test exercise at all. So, it makes me think that they can be because of communication glitches, running out of memory or other bugs. For example, in a server with little memory (6GB) and low CPU capacity, In either weak or strong servers I sometimes get one of these:

Anyway, these problems do not appear in the test exercise, so my initial worry that multiple IO::Async::Loop objects somehow clash must be unfounded. I am now concentrating in how I send data to the socket, receive it, close the socket when had enough.

Here is how I do it (the file lib/MY/A.pm in the provided repository):

package MY::A; use strict; use warnings; use IO::Async::Loop; use Future; use Future::AsyncAwait; use Net::Async::WebSocket::Client; our $VERSION = '0.01'; sub new { my ($class, $params) = @_; $params //= {}; my $self = { 'max-hellos' => (exists($params->{'max-hellos'})&&defined($par +ams->{'max-hellos'})) ? $params->{'max-hellos'} : 4, 'websocket-uri' => (exists($params->{'websocket-uri'})&&define +d($params->{'websocket-uri'})) ? $params->{'websocket-uri'} : 'wss://echo.websocket.org', }; bless $self => $class; return $self; } async sub fetch { my ($self, $params) = @_; my $URI = $self->{'websocket-uri'}; my $MAX_HELLOS = $self->{'max-hellos'}; my $request = Protocol::WebSocket::Request->new( host => $URI, resource_name => __PACKAGE__ ); my $loop = IO::Async::Loop->new; my @data_received; my $num_items_received = 0; my $client = Net::Async::WebSocket::Client->new( on_text_frame => sub { my ( $clientself, $frame ) = @_; return unless $frame =~ /hello/; $num_items_received++; push @data_received, $frame; print __PACKAGE__." : on_text_frame() : got # ${num_items_rece +ived}: ${frame}\n"; # the 1st item is sent from the websocket like 'Request served + by 4d896d95b55478' # so we will save this but don't count it in the below test if( $num_items_received >= $MAX_HELLOS ){ print __PACKAGE__." : on_text_frame() : CLOSING client $cl +ientself.\n"; # we have received enough items, # stop the loop, is this the right way to do it? $loop->stop; $clientself->close_when_empty; # even if we stopped the loop, # data is kept added unless we return() here #return; } }, ); print __PACKAGE__." : adding client $client to the loop ...\n"; $loop->add( $client ); await eval { $client->connect( url => $URI, ) }; if( $@ ){ print STDERR __PACKAGE__." : failed to connect to URI '$ +{URI}'.\n"; return undef } # NOTE: $client will CLOSE after 4 items received # here we send 8 items, $client does not seem to be closed, # neither does $loop! for my $i (1..$MAX_HELLOS){ my $ts = "hello from ".__PACKAGE__." #${i}"; print __PACKAGE__." : sending data to socket : $ts\n"; $client->send_text_frame($ts); sleep(1); } $loop->run; #$client->close_when_empty if $client; #my $retdata = Future->done(\@data_received); #return $retdata; return \@data_received; } 1;

thank you, bw bliako

Replies are listed 'Best First'.
Re^3: IO::Async::Loop in multiple modules all loaded - code provided
by ikegami (Patriarch) on Feb 18, 2026 at 20:35 UTC

    which means there are instantiated loop object in each fetch() running, not a singleton.

    That's not right. IO::Async::Loop->new returns a singleton.

    sub new { return our $ONE_TRUE_LOOP ||= shift->really_new; }

    That shouldn't be a problem, though. If your code is correct, it doesn't matter if multiple modules use the same loop.

      Thanks for the information, it was unclear to me.

      That shouldn't be a problem, though. If your code is correct, it doesn't matter if multiple modules use the same loop.

      Or too correct! As, I was doing a $loop->stop after closing the websocket.

Re^3: IO::Async::Loop in multiple modules all loaded - code provided
by Anonymous Monk on Feb 18, 2026 at 18:23 UTC
    TL;DR: I can have a loop in each module

    Can't comment on anything else in your question, but doesn't this line contradict the above quote?

      yes, indeed after the answers to my question, including yours, I now realise that there is only one loop. Thank you.