[racket] plot-frame does not wait at end of process

From: Eli Barzilay (eli at barzilay.org)
Date: Sun Mar 17 17:41:40 EDT 2013

Four hours ago, Laurent wrote:
> Thank you Robby, yes it helps.
> 
> Based on this, I gave a try at writing a small example that
> describes some particularities of using yield or sync or creating a
> new eventspace with or without a thread:  [...]

I think that like Robby said, `yield' should be taken as something
that is needed rarely, only when you're doing some kind of nested GUI
stuff.  So to go back to the original question (hence reverting the
subject line), here are some examples that I think show why `plot'
should change back, and I think that the last example shows an easier
way to deal with the main thread blocking.  See the comments.

-------------------------------------------------------------------------------
#lang racket/gui

;; Cheap hack that mimics a plot window.
(define (popup title)
  (define f (new frame% [label title] [min-width 100] [min-height 100]))
  (define c
    (new (class canvas%
           (define/override (on-char e)
             (when (eq? 'escape (send e get-key-code)) (send f show #f)))
           (super-new))
         [parent f]
         [paint-callback (λ(c dc) (send* dc (draw-line 0 0 100 100)
                                            (draw-line 0 100 100 0)))]))
  (send f show #t))

(cond
  ;; Shows the original problem: no gui is done until EOF.
  [#f (for ([title (in-lines (current-input-port))])
        (popup title))]
  ;; Laurent's solution: each popup has its own eventspace; kind of
  ;; works, but wasting resources (each eventspace = a new thread), and
  ;; EOF quits and kills all windows.
  [#f (for ([title (in-lines (current-input-port))])
        (parameterize ([current-eventspace (make-eventspace)])
          (popup title)))]
  ;; Naive solution: put the reading in a side thread, but since no
  ;; windows are generated quickly enough, it just exists.
  [#f (thread (λ() (for ([title (in-lines (current-input-port))])
                     (popup title))))]
  ;; Robby's solution: like the above, but have the first read happen on
  ;; the main thread.
  [#f (popup (read-line))
      (thread (λ() (for ([title (in-lines (current-input-port))])
                     (popup title))))]
  ;; IMO this is simpler: one new thread as before, but this is for the
  ;; gui now (and implied by the new eventspace), but it still just
  ;; kills all popups on EOF for the same reason as above.
  [#f (parameterize ([current-eventspace (make-eventspace)])
        (for ([title (in-lines (current-input-port))])
          (popup title)))]
  ;; Simple solution: wait for the gui to be done after reading is done.
  [#f (parameterize ([current-eventspace (make-eventspace)])
        (for ([title (in-lines (current-input-port))])
          (popup title))
        (void (sync current-eventspace)))]
  ;; And finally, the *usual* case where there's no main-thread
  ;; blocking, which is why this subject came up, will now Just Work™.
  [#t (popup "Foo")])
-------------------------------------------------------------------------------

-- 
          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                    http://barzilay.org/                   Maze is Life!


Posted on the users mailing list.