Processes

The "processes" branch of muSE has an implementation of a notion of processes as an abstraction that helps model concurrently running tasks. More...

Collaboration diagram for Processes:

Modules

 Internals
 

A muSE environment contains a circular list of processes called the "process ring" which it cycles through, spending a bit of attention on each process before switching to the next.


Functions

muse_cell fn_spawn (muse_env *env, void *context, muse_cell args)
muse_cell fn_this_process (muse_env *env, void *context, muse_cell args)
muse_cell syntax_atomic (muse_env *env, void *context, muse_cell args)
muse_cell fn_receive (muse_env *env, void *context, muse_cell args)
muse_cell fn_run (muse_env *env, void *context, muse_cell args)
muse_cell fn_post (muse_env *env, void *context, muse_cell args)
muse_cell fn_process_p (muse_env *env, void *context, muse_cell args)
muse_cell fn_with_timeout_us (muse_env *env, void *context, muse_cell args)

Detailed Description

The "processes" branch of muSE has an implementation of a notion of processes as an abstraction that helps model concurrently running tasks.

Every muSE environment is initialized with a main process through which all API calls enter and exit. A muSE expression may spawn off additional processes using the spawn function. The evaluator may switch to another process upon any invocation of muse_apply(). Therefore, process switching appears to be pre-emptive at the Scheme code level, but evaluation is atomic at the C code level unless explicitly pre-empted in a muse_apply(). You can force the evaluation of any expression to occur atomically using the atomic construct.

The basic mechanism by which processes communicate is by sending messages to each other. A process's pid serves as the function to use to send it messages, which can be arbitrary s-expressions. A process receives messages sent to its mailbox using the receive function, which might block until a message is available or a timeout is reached.

It is possible for any process to yield an arbitrary chunk of time to other processes using the run expression.

Each process is given its own namespace of symbol values. This means a process cannot change the value of a symbol that is being used by another process. When one process spawns another, the created process inherits the creating process's symbol values. If it subsequently changes the symbol values, the changes are not visible to the process that created it. However, if two processes share an object such as a list, both processes can modify the contents of the object. The only constructs available to coordinate such modifications are message passing and atomic blocks.


Function Documentation

muse_cell fn_spawn ( muse_env env,
void *  context,
muse_cell  args 
)
 (spawn (fn () [body]) [attention]) -> pid 

Spawns a new process which will evaluate the given thunk. The (optional) attention value is a positive integer giving the number of reductions to perform in the created process before yielding to other processes. The default value is 10.

The result of the spawn expression is a pid using which you can identify the created process and send messages to it by using the pid as a normal function.

The process will end when the thunk completes evaluation. So if you want to create a server process, you can express it as an infinitely tail recursive function. (Tail recursive calls are stack optimized.)

References create_process(), init_process_mailbox(), MUSE_DEFAULT_ATTENTION, prime_process(), and process_id().

muse_cell fn_this_process ( muse_env env,
void *  context,
muse_cell  args 
)
 (this-process) 

Evaluates to the pid of the process in which it is evaluated.

References process_id().

muse_cell syntax_atomic ( muse_env env,
void *  context,
muse_cell  args 
)
 (atomic ...body...) 

Behaves like do, but evaluates the entire body atomically, i.e. without switching to another process, as long as you don't use the pausing functions receive and run.

References enter_atomic(), leave_atomic(), and MUSE_NIL.

muse_cell fn_receive ( muse_env env,
void *  context,
muse_cell  args 
)
 (receive [pid] [timeout-us]) 

Waits for and returns the next message in the process' mailbox. It has four forms -

  • (receive)
  • (receive pid)
  • (receive timeout-us)
  • (receive pid timeout-us)

If a process-id is given as the argument, it waits until a message is received from that specific process. If a timeout value (in microseconds) is given, it waits until either a message is received or the timeout expires. If the timeout expired, the receive expression evaluates to MUSE_NIL - i.e. to ().

References muse_elapsed_us(), MUSE_FLOAT_CELL, MUSE_INT_CELL, MUSE_NATIVEFN_CELL, MUSE_NIL, and switch_to_process().

muse_cell fn_run ( muse_env env,
void *  context,
muse_cell  args 
)
 (run [duration-us]) 

If the duration argument is omitted, the expression never terminates and the process becomes blocked. If a duration is given (in microseconds), the process yields time to other processes for at least that much time. There is no accuracy guarantee for the timing.

References muse_elapsed_us(), MUSE_NIL, and switch_to_process().

muse_cell fn_post ( muse_env env,
void *  context,
muse_cell  args 
)
 (post msg [pid]) 

Allows you to post an arbitrary sexpr as a message to the current process. The difference between using post and pid (as a function) is that when posting a message using pid, the message consists of the argument list and the pid of the sending process is prepended to this list. If you use "post", the message is the first argument - as is. This means "post" is the only way to post, for example, a symbol or a number as the message itself.

An important use for this function is to postpone the processing of a message in situations where how to process it cannot be determined at the time the message is received. If you supply an optional pid, a message can be diverted to another process without modification. In this case, the message is not posted to the current process.

Ex: Postponing the processing of a message -

 (case (receive)
    (pattern-1 ....)
    (pattern-2 ....)
    ...
    (any (post any)))

References _is_pid, muse_message(), MUSE_NIL, and post_message().

muse_cell fn_process_p ( muse_env env,
void *  context,
muse_cell  args 
)
 (process? pid) 

Evaluates to pid if it is a valid process id and to () if it isn't.

References _is_pid.

muse_cell fn_with_timeout_us ( muse_env env,
void *  context,
muse_cell  args 
)
 (with-timeout-us 'id us ...body...) 

Evaluates body like a do statement does, but imposes the given timeout for it. If the timeout expires during the evaluation of the body, it raises the ('timeout 'id given-us elapsed-us) exception.

References muse_do(), muse_force(), MUSE_NIL, MUSE_SYMBOL_CELL, and push_timeout().

Generated on Fri Jun 18 14:49:38 2010 for muSE by  doxygen 1.6.3