Lowlevel documentation

This commit is contained in:
Tony Garnock-Jones 2013-04-26 16:32:41 -04:00
parent c355eaa4a5
commit 8df8ecd215
6 changed files with 255 additions and 21 deletions

View File

@ -28,11 +28,27 @@ noisy, crowded, even chaotic context, rather than in a quiet place
systematically going through their inboxes.
@section{What is a process, what are event handlers?}
@deftech[#:key "process"]{Processes} are ...
@section{What is a VM?}
@section{Subscription and Advertisement}
@deftech[#:key "vm"]{Virtual Machines (VMs)} are ...
@section{Endpoints: Subscription and Advertisement}
@deftech{Endpoints} are ...
**** orientation
**** topics and patterns
**** topics, patterns and messages
**** interest-type
**** roles
Always used to describe the role some process is playing in a
conversation. Can be used by the currently-running process to describe
some role it wishes to play, or can be carried in some
@racket[EndpointEvent] to describe the role some @emph{peer} process
is playing in a conversation.
@section{Presence}
@section{Nesting, relaying, and levels of discourse}

View File

@ -4,11 +4,11 @@
@title{Examples}
@section{TCP echo Server}
@section{TCP echo server}
Here is a complete Marketplace program, @tt{examples/echo-paper.rkt}:
Here is a complete Marketplace program:
@#reader scribble/comment-reader (racketmod marketplace
@#reader scribble/comment-reader (racketmod #:file "examples/echo-paper.rkt" marketplace
(endpoint #:subscriber (tcp-channel ? (tcp-listener 5999) ?)
#:conversation (tcp-channel from to _)

View File

@ -2,18 +2,224 @@
@require[racket/include]
@include{prelude.inc}
@require[(for-label "../main.rkt")]
@title{Low-level interface}
@section{Handler functions}
@section{Events}
@defmodule[marketplace]
@section{Handler Functions}
At its heart, the interface between each @tech{process} and its
containing @tech{VM} is based on @emph{handler functions} exchanging
@emph{event} and @emph{action} structures with the VM. Both events and
actions are simple Racket structures.
Each handler function is always associated with a particular
@tech{endpoint}, registered with the VM via
@racket[endpoint]/@racket[endpoint:]/@racket[add-endpoint]. A handler
function for a given process with state type @racket[State] has type:
@racketblock[(EndpointEvent -> State -> (Transition State))]
That is, given an @racket[EndpointEvent] followed by the process's
current state, the handler should reply with a @racket[Transition]
containing a new process state and a collection of @racket[Action]s.
@deftogether[(
@deftype[(Handler State) (TrapK State)]
@deftype[(TrapK State) (EndpointEvent -> (InterruptK State))]
@deftype[(InterruptK State) (State -> (Transition State))]
)]{
Typed Racket types capturing various notions of handler function.
}
@section{Endpoint Events}
@deftogether[(
@deftype[EndpointEvent (U PresenceEvent AbsenceEvent MessageEvent)]
@deftype[PresenceEvent presence-event]
@deftype[AbsenceEvent absence-event]
@deftype[MessageEvent message-event]
)]{
Endpoint events are passed to handler functions by VMs, conveying some
change in the world the process lives in. An endpoint event can signal
the arrival or departure of a conversational peer, or can deliver a
message that has been sent on a VM's IPC facility.
}
@defstruct*[presence-event ([role Role]) #:prefab]{
Indicates the arrival of a new conversational partner: an endpoint
with a topic that intersects our own, with @racket[Orientation]
opposite to our own.
The @racket[presence-event-role] describes the arriving peer, or more
precisely, describes the shared interest between ourselves and the new
peer. In particular, the @racket[role-orientation] of the
@racket[presence-event-role] is the orientation that the @emph{peer}
supplied in its @racket[add-endpoint] structure.
}
@defstruct*[absence-event ([role Role] [reason Any]) #:prefab]{
Indicates the departure of an existing conversational partner, through
either an explicit @racket[delete-endpoint] action or the implicit
deleting of all of a process's endpoints when a process exits.
The @racket[absence-event-role] describes the departing peer,
analogously to @racket[presence-event-role].
}
@defstruct*[message-event ([role Role] [message Message]) #:prefab]{
Indicates the arrival of a message matching the topic pattern in the
handler's @tech{endpoint}.
}
@section{Actions}
**** Communication-related
***** add-endpoint
***** delete-endpoint
***** send-message
**** Process- and scheduling-related
***** spawn
***** quit
***** yield
**** Cross-layer
***** at-meta-level
@deftogether[(
@deftype[(Action State) (U (PreAction State) (yield State) (at-meta-level State))]
@deftype[(PreAction State) (U (add-endpoint State) delete-endpoint send-message (spawn State) quit)]
)]{
Actions are requests from a process to its containing VM. If wrapped
in an @racket[at-meta-level] structure, the action is to apply to
@emph{the VM's own containing VM}; otherwise, the action applies to
the process's containing VM.
}
@deftogether[(
@defstruct*[at-meta-level ([preaction (PreAction State)]) #:prefab]
@deftype[(AtMetaLevel State) (at-meta-level State)]
)]{
An @racket[at-meta-level] structure wraps a plain action, and makes it
apply to the outer VM instead of the inner VM (the default).
}
@deftogether[(
@defstruct*[yield ([k (InterruptK State)]) #:prefab]
@deftype[(Yield State) (yield State)]
)]{
Because current VM implementations are cooperatively scheduled, it can
sometimes be necessary to explicitly yield the CPU to other processes
using a @racket[yield] action. When control returns to the yielding
process, the @racket[yield-k] is invoked.
}
@subsection{Endpoints and Messages}
@deftogether[(
@defstruct*[add-endpoint ([pre-eid Any] [role Role] [handler (Handler State)]) #:prefab]
@deftype[(AddEndpoint State) (add-endpoint State)]
)]{
Creates a new endpoint subscribing to the given @racket[Role]. When
events pertaining to the given role occur, the @racket[Handler] is
invoked.@note{If invoked @racket[at-meta-level], subscribes to events
in the containing VM's container.}
The name of the new endpoint will be the @racket[pre-eid]; it must be
unique within the current process, but otherwise can be any value at
all. If the endpoint's name matches an existing endpoint, and the new
role is the same as the existing endpoint's role, the handler function
is @emph{replaced} in the existing endpoint.
To delete an endpoint, perform a @racket[delete-endpoint] action built
with the name of the endpoint to delete.
}
@deftogether[(
@defstruct*[delete-endpoint ([pre-eid Any] [reason Any]) #:prefab]
@deftype[DeleteEndpoint delete-endpoint]
)]{
Deletes an existing endpoint named @racket[pre-eid]. The given
@racket[reason] is passed along to peer endpoints as part of an
@racket[absence-event].
If no specific reason is needed, it is conventional to supply
@racket[#f] as the @racket[delete-endpoint-reason].
}
@deftogether[(
@defstruct*[send-message ([body Message] [orientation Orientation]) #:prefab]
@deftype[SendMessage send-message]
)]{
Sends a message to peers.@note{Or, if @racket[at-meta-level], peers of
the containing VM.} The given @racket[Orientation] should describe the
role the sender is playing when sending this message: usually, it will
be @racket['publisher], but when the message is @emph{feedback} for
some publisher, it will be @racket['subscriber]. See also
@racket[send-feedback].
}
@subsection{Process Management}
@deftogether[(
@defstruct*[spawn ([spec process-spec] [k (Option (PID -> (InterruptK State)))] [debug-name Any])
#:prefab]
@defstruct*[process-spec ([boot (PID -> CoTransition)]) #:prefab]
@deftype[CoTransition (All (Result) (All (State) (Transition State) -> Result) -> Result)]
@deftype[(Spawn State) (spawn State)]
@deftype[ProcessSpec process-spec]
)]{
A @racket[spawn] requests the creation of a sibling process@note{If
wrapped in an @racket[at-meta-level], the new process will instead be
a sibling of the creating process's VM.}. The @racket[spawn-k] runs in
the context of the @emph{creating} process, communicating to it the
PID of the new process.
The @racket[spawn-spec] describes the new process to be created. Its
@racket[process-spec-boot] field is a function taking the PID of the
new process and returning a "cotransition". Cotransitions use a
second-order encoding of existential types to guarantee that the VM
remains oblivious to the specific process state type of the new
process. The downside of this approach is its syntactic and type
complexity: see @racket[spawn:] for an easier-to-use, higher-level
approach.
}
@deftogether[(
@defstruct*[quit ([pid (Option PID)] [reason Any]) #:prefab]
@deftype[Quit quit]
)]{
Kills a sibling.@note{Or, if @racket[at-meta-level], a sibling of the
containing VM.} If @racket[quit-pid] is @racket[#f], kills the current
process; otherwise, kills the process with the given PID. The
@racket[quit-reason] is passed on to peers of currently-active
endpoints in the process to be killed, as part of a
@racket[absence-event], just as if each active endpoint were deleted
manually before the process exited.
If no specific reason is needed, it is conventional to supply
@racket[#f] as the @racket[quit-reason].
}
@deftype[PID Number]{
In the current VM implementations, process IDs are simply numbers.
PIDs are scoped to and allocated by each individual VM instance.
}

View File

@ -2,7 +2,7 @@
@require[racket/include]
@include{prelude.inc}
@title[#:tag "marketplace"]{Marketplace: Functional Systems Programming}
@title[#:tag "marketplace"]{Marketplace: A Functional Operating System}
@author[(author+email "Tony Garnock-Jones" "tonyg@ccs.neu.edu")]

View File

@ -1,13 +1,13 @@
#+STARTUP: nofold
** Overview
** Overview and Motivation
** Concepts
*** What is a process, what are event handlers?
*** What is a VM?
*** Subscription and Advertisement
**** orientation
**** topics and patterns
**** topics, patterns and messages
**** interest-type
**** roles
*** Presence

View File

@ -1,3 +1,15 @@
;; -*- scheme -*-
(require scribble/racket
scriblib/footnote
(for-label racket))
(for-syntax racket)
(for-label typed/racket/base))
;; TODO: make it display "=" instead of ":" connecting the defined
;; type to the definition.
(define-syntax deftype
(lambda (stx)
(syntax-case stx ()
[(_ (t a ...) d desc ...)
#`(defthing #:kind "type" t #,(syntax/loc #'d (All (a ...) d)) desc ...)]
[(_ t d desc ...)
#`(defthing #:kind "type" t d desc ...)])))