fibers icon indicating copy to clipboard operation
fibers copied to clipboard

Implement operations for waiting for readability / writability

Open emixa-d opened this issue 3 years ago • 4 comments

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)))

emixa-d avatar Sep 16 '21 15:09 emixa-d

Let's first run the test suite of guile-fibers and scheme-gnunet ...

emixa-d avatar Sep 16 '21 15:09 emixa-d

The test suite succeeded!

emixa-d avatar Sep 16 '21 16:09 emixa-d

Now rebased. Seems to work well for scheme-gnunet so far. (If on guix, you can try guix build gnunet-scheme.)

emixa-d avatar Feb 05 '22 16:02 emixa-d

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.

emixa-d avatar Jul 23 '22 17:07 emixa-d

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?

civodul avatar Nov 09 '22 11:11 civodul

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.

emixa-d avatar Nov 09 '22 11:11 emixa-d

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!

civodul avatar Nov 10 '22 14:11 civodul