Corrections to the guide's places entry

This commit is contained in:
Matthew Flatt 2011-09-05 18:10:00 -06:00 committed by Kevin Tew
parent a6b4b42982
commit cf772ceebd

View File

@ -6,16 +6,18 @@
The @racketmodname[racket/place] library provides support for The @racketmodname[racket/place] library provides support for
performance improvement through parallelism with the @racket[place] performance improvement through parallelism with the @racket[place]
form. Two places communicate using @racket[place-channel-put] and form. The @racket[place] form creates a @deftech{place}, which is
@racket[place-channel-get] functions. Places contains the full effectively a new Racket instance that can run in parallel to other
expressive power of the Racket language. However, the places design places, including the initial place. The full power of the Racket
restricts both the methods of inter-place communication and the type language is available at each place, but places can communicate only
of values permitted inside communication messages. through message passing---using the @racket[place-channel-put] and
@racket[place-channel-get] functions on a limited set of
values---which helps ensure the safety and independence of parallel
computations.
The @racket[place] form spawns a new pristine racket execution As a starting example, the racket program below uses a @tech{place} to
context, which the OS can schedule on any available processor. As a determine whether any number in the list has a double that is also in
starting example, the racket program below uses a place to determine the list:
whether any number in the list has a double that is also in the list:
@codeblock{ @codeblock{
#lang racket #lang racket
@ -28,66 +30,67 @@ whether any number in the list has a double that is also in the list:
(= i2 (* 2 i))))) (= i2 (* 2 i)))))
(define (main) (define (main)
(define p (place ch (define p
(define l (place-channel-get ch)) (place ch
(define l-double? (any-double? l)) (define l (place-channel-get ch))
(place-channel-put ch l-double?))) (define l-double? (any-double? l))
(place-channel-put ch l-double?)))
(place-channel-put p (list 1 2 4 8)) (place-channel-put p (list 1 2 4 8))
(printf "Has double? ~a\n" (place-channel-get p)) (begin0
(place-wait p)) (place-channel-get p))
(place-wait p))
} }
The first argument to the place form is an identifier, which the The identifier @racket[ch] after @racket[place] is bound to a @deftech{place
@racket[place] form binds to an initial place-channel. The remaining channel}. The remaining body expressions within the @racket[place] form
argument expressions form the body of the @racket[place] form. The are evaluated in a new place, and the body expressions use @racket[ch]
body expressions use the initial place-channel to communicate with the to communicate with the place that spawned the new place.
place which spawned the new place.
In the example above, the place form has a body of three expressions. In the body of the @racket[place] form above, the new place receives a
The first receives a list of numbers over the initial place-channel list of numbers over @racket[ch] and binds the list to @racket[l]. It
(@racket[ch]) and binds the list to @racket[l]. The second body then calls @racket[any-double?] on the list and binds the result to
expression calls any-double? on the list and binds the result to @racket[l-double?]. The final body expression sends the
@racket[l-double?]. The last body expression sends the @racket[l-double?] result back to the original place over @racket[ch].
@racket[l-double?] result back to the invoking place over the
@racket[ch] place-channel.
The macro that implements the @racket[place] form performs two actions with In DrRacket, after saving and running the above program, evaluate
subtle consequences. First, it lifts the place body to an anonymous @racket[(main)] in the interactions window to create the new
module-scope function. This has the consequence that any function place. @margin-note*{When using @tech{places} inside DrRacket, the
referred to by the place body must be defined at module-scope. Second, module containg place code must be saved to a file before it will
the place form expands into a @racket[dynamic-place] call, which execute.} Alternatively, save the program as @filepath{double.rkt}
@racket[dynamic-require]s the current module in a newly created place. and run from a command line with
@margin-note{When using places inside DrRacket, the module containg
place code must be saved to a file before it will execute.} @commandline{racket -tm double.rkt}
As part of the @racket[dynamic-require] the current module body is
evaluated in the new place. The consequence of this second action is where the @Flag{t} flag tells @exec{racket} to load the
that places forms must not be called at module-scope or indirectly by @tt{double.rkt} module, the @Flag{m} flag calls the exported
functions which are invoked at module scope. Both of these errors are @racket[main] function, and @Flag{tm} combines the two flags.
demonstrated in the code bellow. Failing to follow this precaution
will result in an infinite spawning of places as each spawned place The @racket[place] form has two subtle features. First, it lifts the
evaluates the module body and spawns an additional place. @racket[place] body to an anonymous, module-level function. This
lifting means that any binding referenced by the @racket[place] body
must be available in the module's top level. Second, the
@racket[place] form @racket[dynamic-require]s the enclosing module in
a newly created place. As part of the @racket[dynamic-require], the
current module body is evaluated in the new place. The consequence of
this second feature is that @racket[place] should appear immediately
in a module or in a function that is called in a module's top level;
otherwise, invoking the module will invoke the same module in a new
place, and so on, triggering a cascade of place creations that will
soon exhaust memory.
@codeblock{ @codeblock{
#lang racket #lang racket
(provide main) (provide main)
; do not do this ; Don't do this!
(define p (place ch (define p (place ch (place-channel-get ch)))
(place-channel-get ch)))
(define (indirect-place-invocation) (define (indirect-place-invocation)
(define p2 (place ch (define p2 (place ch (place-channel-get ch))))
(place-channel-get ch))))
; Don't do this, either!
; do not do this either
(indirect-place-invocation) (indirect-place-invocation)
} }
The example above is executed by running @exec{racket -tm double.rkt}
from the command line. The @Flag{t} tells racket to load the
@tt{double.rkt} module. The @Flag{m} instructs racket to run the
@racket[main] module.