lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


After some (rather murky) thinking, I believe that the natural behavior for a "task" going out of scope is to be killed right away.

So I think I'll make all library objects __toclose-able in this meaning, make sure they are always held weakly by the library, and see how it looks.

Jorge


On 23/9/22 03:08, Sean Conner wrote:
It was thus said that the Great John Belmonte once stated:
On Tue, Sep 20, 2022 at 10:21 PM Jorge Visca <xxopxe@gmail.com> wrote:

I wonder how would you handle waiting on several
signals?
First, it needs cancellation (coming in part 3).

Given that, I usually implement a `wait_any()` utility.  The inputs can be
any function that uses return of control to signal the event.  (For
example, the async_wait() method of Event.)  Then:

```
-- run these functions concurrently; when one returns, cancel the others
async_wait_any(
     event_foo.async_wait,
     async_wait_for_bar,
     async_do_baz,
     ...)
```
   I've been playing around with my own implementation of this for
org.conman.nfl [1].  I got cancellation working (using coroutine.close()),
so the following bit of code works as intended:

	local tcp     = require "org.conman.nfl.tcp"
	local nursery = require "nursery"

	local function get_quote(list)
	  local conn = tcp.connect('brevard.conman.org','qotd')
	  if conn then
	    for line in conn:lines() do
	      table.insert(list,line)
	    end
	    conn:close()
	  end
	end
	
	-- get_gopher and get_gemini not shown, but are similar
	-- in nature.

	local data_quote  = {} -- used to accumulate the data
	local data_gopher = {} -- from each of these services
	local data_gemini = {}

	do
	  local _ <close> = nursery(1) -- I don't care about the name
	        :spawn(get_gemini,data_gemini)	-- so '_' is it!
	        :spawn(get_gopher,data_gopher)
	        :spawn(get_quote,data_quote)
	end

   The nursery:spawn() function returns the nursery so calls can be chained
like this.  The call nursery(1) sets up a timeout for the entire nursery
collection and will cancel any current jobs still running in the nursery.
You can also write it as:

	nursery() -- no timeout specified, so take as long as you like
		:spawn(get_gemini,data_gemini)
		:spawn(get_gopher,data_gopher)
		:spawn(get_quote,data_quote)
		:wait() -- this is also the __close() metamethod

   I also support a wait_any(), which will wait until one of the jobs
finishes, then cancel the others:

	nursery()
		:spawn(get_gemini,data_gemini)
		:spawn(get_gopher,data_gopher)
		:spawn(get_quote,data_quote)
		:wait_any()

   I'm awaiting futher installments of the series, as I can't follow the
documentation for Python Trio, since I don't do Python.

   -spc

[1]	My event/coroutine driver:
	https://github.com/spc476/lua-conmanorg/blob/master/lua/nfl.lua