guile-user
[Top][All Lists]
Advanced

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

Re: The equivalent of racket's break-thread in guile?


From: Taylan Ulrich B.
Subject: Re: The equivalent of racket's break-thread in guile?
Date: Fri, 31 May 2013 13:20:00 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (berkeley-unix)

This is only partially relevant to the topic, but I'm very fond of the
run-loop/operation-queue based solution to the problem of ad-hoc
interleaved code execution in a certain thread, should the application
also otherwise lend itself to that generic architecture.

I have some spare time so let me elaborate, whatever it's worth.

There is no real interruption; a queued function on the run-loop will
execute atomically, but if the functions are kept at appropriate sizes
(don't "block the thread" for too long) it works well and is very easy
to use: asynchronous execution is started with e.g. `begin-thread'
wherever desired, and at any point some `begin-in-original-thread'
abstraction can be used to "switch back" to the original thread (by
inserting a function into the front of the execution queue),
"interrupting" its usual flow cleanly at the boundaries of a top-level
function-call in the run-loop (a queued operation), thus a primitive but
intuitive kind of synchronization is automatically achieved, making
further purpose-specific synchronization very easy with plain booleans
and such.

Cheap pseudo-code for a "set-up interface" function on a GUI run-loop:

(letrec
  ((request (uri-request image-uri))
   (cancel #f)
   (start-button
    (button #:label "Fetch image"
            #:action (lambda ()
                       (button-disable start-button)
                       (button-enable cancel-button)
                       (begin-thread
                         (let ((image-data (request-execute request)))
                           (begin-in-original-thread
                             (unless cancel
                               (button-disable cancel-button)
                               (display-image image-data))))))))
   (cancel-button
    (button #:label "Cancel"
            #:action (lambda ()
                       (request-cancel request)
                       (set! cancel #t)
                       (button-enable start-button)
                       (button-disable cancel-button)))))
  (display-button start-button)
  (display-button cancel-button)
  (button-disable cancel-button))

Since the URI request is executed in parallel, a race might happen with
regard to it finishing and being canceled.  On the other hand, access to
the `cancel' boolean is synchronous because all bodies of code that use
it are operations queued on the same run-loop (button actions are queued
on the run-loop).

Maybe I'm biased because the bulk of my day-to-day programming consists
of user-interface heavy applications which lend themselves very well to
a run-loop based architecture, and also I'm using a language that isn't
garbage-collected so cleaning up behind a ruthlessly interrupted/killed
thread can be a hassle; but I believe this method of parallelism and
synchronization to be significantly cleaner than manual/actual
interruption of threads.  I'm not aware of any Guile library that
implements run-loops and dispatch queues yet; perhaps I should try to
implement one.

Taylan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]