fibers
fibers copied to clipboard
Implement operations for waiting for readability / writability
I have used a previous version of this patch in https://notabug.org/maximed/scheme-gnunet/ for a while to implement message queues. It can be used like:
;; Untested, but I have been doing something similar for a while
;; in <https://notabug.org/maximed/scheme-gnunet/src/master/gnu/gnunet/mq-impl/stream.scm>.
(let ((old-waiter (current-read-waiter)))
(let/ec escape
(parameterize ((current-read-waiter
(lambda (port)
(if (eq? port my-port)
(perform-operation
(choice-operation (wait-until-port-readable-operation my-port))
(wrap-operation (wait-operation condition)
(lambda () (escape 'interrupted))))
(old-waiter port)))))
(read-line my-port)))
Let's first run the test suite of guile-fibers and scheme-gnunet ...
The test suite succeeded!
Now rebased. Seems to work well for scheme-gnunet so far. (If on guix, you can try guix build gnunet-scheme
.)
After no comments for 1.5 years and as it works well for scheme-gnunet, I will merge it after a week unless someone has some comments.
Hi @emixa-d!
I'm (very) late to the party. I had similar needs in the Shepherd, which I solved with this procedure:
(define (wait-for-readable ports)
"Suspend the current task until one of @var{ports} is available for
reading."
(suspend-current-task
(lambda (sched k)
(for-each (lambda (port)
(schedule-task-when-fd-readable sched
(port-read-wait-fd port)
k))
ports))))
It adds a dependency on (ice-9 ports internal)
, but it has the advantage that it doesn't require low-level fiddling with operations.
Would it be an option for the kind of use cases you had in mind?
No, because my use case is fiddling with operations. More precisely, in my use case, I need to wait for the port to be readable/writable or for a condition to be signalled. The tool to do this 'or' is choice-operation
, hence an operation. See: https://git.gnunet.org/gnunet-scheme.git/tree/gnu/gnunet/mq-impl/stream.scm#n282.
I guess I could avoid it somehow by creating a pipe and a fiber that waits for condition signalled and then writes a byte that pipe (essentially the 'pipe' trick for C signals, IIUC), but that sounds inconvenient to me and less general.
No, because my use case is fiddling with operations. More precisely, in my use case, I need to wait for the port to be readable/writable or for a condition to be signalled. The tool to do this 'or' is
choice-operation
, hence an operation. See: https://git.gnunet.org/gnunet-scheme.git/tree/gnu/gnunet/mq-impl/stream.scm#n282.
I see, that makes sense.
Thanks for explaining!