Communicating Sequential Processes
A formal language for describing concurrent systems
Processes
A process represents the behaviour pattern of an object. It
consists of an alphabet, which is the set of the possible atomic
events an object can engage on. There is no distinction between
events originated by the user of the object or by the object
itself.
The alphabet of process
is denoted as
and the set of traces of
is denoted as
.
Two processes are considered independent if their
alphabets are disjoint.
A process can be defined in terms of itself, like
.
A process can be defined as a function
that takes an event and results in a process, and where its
domain must be a subset of the alphabet. The function may return
to represent termination.
Two processes are equal if their event choices are the same
and each resulting process is the same. The processes
and
are the same if
.
If two objects define the same process, then they are
considered equal, therefore there exists only one object that
defines a process. A more formal definition for a process such
as
is
.
Given a function
that maps an event to a process, the unique-type definition can
be generalized as
,
where the second argument to
is the process itself, in order to support recursion.
Operators
The prefix operator
()
takes an event and a process and describes the process that
engages in a given event and then behaves like the subsequent
process, for example
.
Notice that
is equivalent to
.
The choice operator
()
takes two prefix applications (its not an operation on
processes) and describes a process that has a choice over what
event to engage on, for example
.
Notice that
.
The events on the involved prefixes must be different, as
is considered invalid.
The alphabet of the resulting process consists of the prefix
events and the alphabets of the involved processes:
.
There exists a shorthand to define choices over a set. Given
,
the shorthand
evaluates to
.
If the set of choices is the empty set, the resulting process is
the broken process. Given
,
if
where
for all
,
then
.
A process
is a subset of process
if they share the same alphabets and the traces of
can all be consumed by
.
This is denoted as:
.
Of course,
.
If two processes are subsets of each other, then they must be
equal:
.
The subset operation is transitive:
.
Finally, a process is always the superset of its broken process:
.
Given a variable
that is either
or
,
the process
behaves like
if
,
and like
otherwise. This operator obeys the following laws:
Given a boolean expression
and a process
,
the process
is the machine that restarts
while
is
:
.
Process Mapping (or
Change of Symbol)
Given a function
that maps the alphabet (takes the alphabet of a process and
returns a new set of the same size), a process
,
and an event
,
then
represents the process that engages in
(the actual function application) whenever
engages in
.
The function must be injective, so that
makes functional sense.
It follows that
.
The traces of the mapped process are
.
Notice the mapping function always preserves the broken process,
as in that case it would map over an empty list of choices:
.
Notice that process mapping distributes over the composition
operator:
.
When it comes to consuming a trace
,
then
.
Given the choices shorthand definition of a process
non-recursive process:
.
For example, consider
and
.
In that case,
.
Given a sequential process
,
then
must hold.
Given an arbitrary interleaving
,
.
A process defined by mapping diverges when its original
process diverges. Given
and
,
.
The failures of a mapped process are defined as
.
The refusals of a mapped process are defined as
.
Concealing a mapped process is defined as
.
Process Labelling
Labelling is a mapping technique to add prefix to all the
events of a process. Its useful when constructing groups of
processes, and where we need to make sure that they are
independent (that their alphabets are disjoint). Process
labelled with
is denoted as
.
The prefix is added before every event, separated by a
period.
For any prefix
,
there exists a function
.
The labelled process
is equivalent to
.
Notice labelling changes the alphabet:
.
For example, consider
.
In that case,
.
Concealment
Concealment creates a new process that behaves like the new
process but with certain events being hidden. This operation
reduces the alphabet of a process and may introduce
non-determinism. Concealing an infinite sequence of consecutive
events leads to divergence.
This operation is defined as
if
,
and as
otherwise. Given the choice shorthand definition
,
concealing such process with
expands to
if
,
otherwise it expands to
where
,
which introduces non-determinism.
The alphabet of a concealed process is
.
The traces of a concealed process are defined as
.
The following laws apply:
and
.
Given a concealed process, its divergences consist its
original divergences plus the new ones potentially created by
the concealment operation:
The alphabet of a concealed process is defined as
.
The failures of a concealed process are defined as:
Subordination
Given
,
is a slave or subordinate process of
if
,
as each action of
can occur if
permits it, while
can freely engage on events of its own (where
).
If we want to conceal communication between master and
subordinate, then we can use the notation
.
Its alphabet is
.
The subordinated process can be given a name in which case
the master will communicate with it using a compound channel
name, while the subordinated process will communicate with its
master through a normal channel pair name. The benefit is that
all communication between the master and the subordinate can’t
be detected from outside as the new subordinate name acts as a
local variable for the master.
For example,
.
Also consider
.
In this case, there is no way
can communicate with
as it doesn’t know about its existance or about its name,
.
- Only the master process can make a choice for the
subordinate:
- The order in which subordinate processes are declared
doesn’t matter:
- The master may communicate with other processes, and such
communication is left outside the subordination:
Communication from the master to the slave looks like this:
.
Conversely, communication from the slave to the master:
.
Communication
Communication between processes is done using events that
sets values on channels. This is described by
the pair
where
and
or the triplet
which includes the process as a prefix (a compound channel
name). Notice that
for any
.
A channel used by
only to send events is an output channel of
.
A channel used by
only to receive events is an input channel of
.
Communication is unidirectional and only between two
processes. Communication between two processes can only happen
if both processes engage in the communication: one listens on a
channel while the other one sends a message through that
channel.
The set of all values that process
can communicate on a channel
is the alphabet of the channel:
.
Given a compound channel name,
.
Communication event pairs must be part of the alphabet of a
process. For two processes to communicate over a channel
,
they need to share the same alphabet on such channel:
.
Given
and
communicate over channel
,
all the possible communication events are inside
.
Given proces
,
the event
sends value
over channel
.
For this to be valid,
.
This event is defined as
.
The communication message can be a more complex expression:
.
The event to wait for a value on a channel is
,
where
takes the value of the received message. This is defined as a
choice over all the valid communication events of that channel:
.
A process can wait in more than one channel using the choice
operator:
.
Variables
is the process that sets
to
.
Its defined as
.
It follows that
and that
.
The assignment operator can be used with multiple variables:
but keep in mind that
as in the first case
may depend on the new value of
.
With regards to the conditional operator:
.
Given a process
,
is the set of all variables that can be assigned within
,
and
is the set of all the variables that
can access. Of course, all variables that can be set can be
accessed:
.
Both sets are subsets of
.
No variable assigned in a process can be accessed by another
concurrent process, so given
and
,
then
.
Deterministic Processes
A deterministic process is a tuple
consisting of two sets: an alphabet and a set of traces. These
laws must be satisfied for a deterministic process to be
valid:
- :
the empty trace is valid on every process
- :
if a trace is valid in a process, then any prefix of the trace
is also valid in the process
- :
all traces consist of elements of the alphabet
A process
is deterministic if it can’t refuse any event in which it can
engage:
.
Deterministic processes can unambiguously pick between events
whenever there is a choice. These processes obey an extra law:
given
then,
.
The process that results by making a process consume a trace
is a process with the same alphabet, and with all traces whose
prefixes were consumed. Given process
and
,
then
.
Of course,
,
and given a function definition,
assuming
.
The choice prefix shorthand notation works like this: given
an alphabet
,
a set of choices
,
and a function
that maps over the set of traces, then
.
The process mapping operation using a function
is defined as
.
Special Processes
Every alphabet has a broken process that never
engages in any event. Given alphabet
,
the broken process is
.
Processes with different alphabets are always considered to be
different, so given alphabets
and
,
if
,
then
.
The traces of the broken object are defined as
.
Every alphabet has a run process that can always
engage, at any given point, in any event of its alphabet. Given
alphabet
,
the run process is
,
or alternatively
,
and it follows that
.
Notice that the run process behaves like a restart process:
.
Given alphabet
,
the
process does nothing and terminates successfully:
.
A process can terminate successfully by behaving like
.
Notice
.
Its traces are
.
Concealing the broken process results in the broken process:
.
Properties
A process is cyclic if in all circumstances it can
go back to its original state. Given process
,
then
.
The broken process is a simple example.
A process
is free from deadlocks if none of its traces lead to
the broken object:
.
Non-deterministic
Processes
A non-deterministic process is defined as a triplet
that stands for the process alphabet, its failures, as a
relation
where
,
and a set of divergences where
and
.
The following laws must hold:
Given
and
,
the
operator is defined as
.
Failures
The failures relation over
is defined as
.
If
is a failure of
then it means that
will refuse
after engaging in
.
Alternatively:
Its interesting that the traces of a process
can be defined in terms of its failures:
.
Divergences
A trace of a process after which the process behaves
chaotically is called a divergence of the process:
.
Of course,
.
Anything concatenated to a divergence is also a divergence:
.
After engaging on a divergence, a process refuses everything:
.
A process defined by choice can’t diverge on its first event,
so its divergences are defined by what happens after it:
.
Refusals
The refusals of a process
are defined as
.
Given a process defined by prefix, such process refuses all
events that it can’t engage in:
.
For any process
,
and
.
If a process refuses a set, then it can refuse any of its
subsets:
.
Also, any event that can’t initially occur in a process can be
added to an existing refusal, and the result will remain a
refusal:
.
Choices
Given processes
and
where
,
is the process that behaves either like
or like
where the selection between them is non-deterministic.
If
and
,
then
.
Then
and
,
or more generally:
.
The
notation stands for
.
Its traces are defined as
where given
:
- If
is only a trace of
:
- If
is only a trace of
:
- If
is a trace of both:
Notice that
,
,
and
.
distributes over
:
and
.
Keep in mind that
doesn’t distribute over a recursive process definition:
unless
.
The traces of the second process is a subset of traces of the
first process. The second process can choose to always engage in
or always engage in
,
while the first one can arbitrarily interleave them.
The concealment of a non-deterministic choice is defined as
.
Given processes
and
where
,
is the process that behaves either like
or like
where the selection between them may be determined by its first
action. If the first action is in
and not in
,
then
is selected. Conversely, if the first action is in
but not in
,
then
is selected. If the first action is in both processes, the
selection remains non-deterministic.
More formally,
and given events
and
,
if
then
,
otherwise
.
Notice that
,
,
and
.
The traces of
are defined as
.
Given a trace
,
then:
- If
,
then
- If
,
then
- If
,
then
Notice that
and
both distribute with each other. Also,
,
but it is possible for
to deadlock on its first step, as
but
.
With regards to divergences, any divergence of
or
is a divergence of
and a divergence of
:
.
If
can refuse
,
then
will refuse
if
is selected, and if
can refuse
,
will refuse it if
is selected:
.
In the case of
,
.
The failures of
are defined as:
Interleaving
Given two processes
and
with the same alphabet,
joins both processes without any interaction or
synchronization. The only case for non-determinism is when both
processes could have engaged in the same event.
Given
and
,
.
The traces of
are arbitrary interleaves of a trace of
and a trace of
,
and are defined as
.
Refusals are defined as:
.
Failures are defined as:
Divergences are defined as:
Of course,
.
and
,
but
.
Also
distributes over
,
but not over
.
Trace consumption has a more complex definition. Given
,
assume
.
Then
.
Special Processes
Given an alphabet
,
is the most non-deterministic process and its represented as
.
There is nothing that it can’t do, and it can’t be extended with
more non-deterministic choices. Notice that
,
,
and
.
For any process
,
.
A function is said to be strict if the result is the
process if
is involved in any of its arguments. For example:
,
,
,
,
and
.
The prefix operator is a counter-example, as
.
The
process can be modelled as
.
It does nothing and refuses everything:
,
but it doesn’t diverge:
.
Notice that for any
,
.
Notice that
given that
doesn’t diverge.
The
process can also be modelled as a non-deterministic process.
Notice that Notice that
given that
doesn’t diverge.
Composition
Two processes can be composed as
to model concurrency. The type of the resulting composition
depends on the relationship between the alphabets of the
composed processes.
- Interaction: if the processes share the
same alphabet
()
- Interleave: if parts of the alphabet
overlap
()
- Pure interleave: if the alphabets are
disjoint
()
Composition is commutative
()
and associative
().
Also
.
Given an interaction, the resulting process is the
intersection between the composed processes. Basically
,
which means that
.
It follows that
and that
.
Given two processes defined with the choice shorthand,
.
If no choices are shared, the result is the broken object:
.
Trace consumption is defined as
.
Given an interleave or a pure interleave,
the resulting process is the concurrent combination of both
processes with potential synchronization points, and it should
consider every possible way in which independent events may
happen. Processes
and
only need to be synchronized on events from
.
Consider two processes
and
.
The events from
will be drawn from
.
Assuming
,
there are three possibilities:
- If
,
then we can advance with both
and
:
- If
,
then we can only advance on
:
- If
,
then we can only advance on
:
Notice
is not a possibility given the definition of
.
The resulting alphabet is
.
The set of valid traces is defined as
which means that the parts of a trace related to
must be valid in
,
the parts related to
must be valid in
,
and the events in a trace must have been drawn from the alphabet
of either
or
.
Consuming a trace
is defined as
.
Notice that if
(which means the composition would be an interaction),
then the previous expression is equal to our
interaction definition:
.
Given composition between two processes that engage on
communication:
.
Notice the act of sending the message remains on the process
definition (think of it as a log that can be conncealed if
desired).
Given sequential processes
and
,
then
is only valid if
.
The failures of a composed process are defined as:
Divergences are defined as:
Restart Processes
Given a process
where
,
is the process that behaves like
until
occurs, and then behaves like
again.
It is defined as
with an alphabet
.
Notice that
.
A process can “save” its state by engaging on a checkpoint
event
.
Given
where
,
is the process that goes back to the state after its more recent
checkpoint or starts all over again if it engages in
.
This is defined as
and
.
is the process that goes back to the state just before the last
if it engages on
.
Its alphabet is defined as
and its behaviour is defined as
and
.
Sequential Processes
A sequential process has
in its alphabet, and engages on it upon successful termination.
can only be the last event a sequential process engages
with.
A trace of a sequential process
is a sentence if
terminates successfully after it engages on it.
Given a composition of a non sequential process
with a sequential process
,
the sequential process dominates the result if its alphabet is a
superset of the non sequential one:
.
Notice that a successfully terminating process (like
)
doesn’t participate in any other event offered by another
concurrent process:
.
Sequential Composition
Given sequential processes
and
with the same alphabet,
is the process that behaves like
until successful termination, and then behaves like
.
If
doesn’t terminate successfully, then neither does
.
Notice that
,
that
and similarly
.
Of course,
.
An infinite loop consisting of sequential composition of a
process with itself is defined as
,
which expands to
.
Given
is an infinite loop and doesn’t terminate, then
is not part of its alphabet:
.
Notice
.
Given one choice:
.
Also, sequential composition is associative:
.
Given
and considering
and
,
then notice that
,
and
.
Given traces
and
where
is not in
,
then
and
.
Also, events after the successful termination event are
discarded:
.
The traces operation is defined like this:
.
Given a deterministic process
,
notice that
.
For non-deterministic processes, this observation is loosen up
to
.
In the case of non-deterministic processes,
distributes over
.
Its refusals are:
Notice that if
can refuse
,
then it can also refuse
.
Failures are defined as:
For non-deterministic sequential composition,
,
as a divergent process must remain divergent.
diverges when
diverges or when
completes successfully and then
diverges:
Interruption
Given sequential processes
and
,
is a type of sequential composition that behaves like
up to an arbitrary event where execution is interrupted, and
then behaves like
.
It must hold that
.
starts on an arbitrary event initially offered by
but not offered by
at all (this ensures determinism):
.
is associative and distributes over
.
Also
and
.
It is defined as
where
.
The catastrophic interrupt event is denoted
.
,
given
,
which describes a process that behaves like
,
until
arbitrarily occurs, and then behaves like
.
Its defined as
.
With regards to traces,
.
Random alternation between
and
is denoted
.
One of the processes will run at any given time, until its
arbitrarily interrupted with the
event, and then will switch to the other process until the same
event occurs again. This is defined as
.
Notice that
and that
.
Also
.
Pipes
Processes with only two channels: an input channel
and an output channel
are called pipes. Given two pipes that are
non-stopping, their composition is also non-stopping.
cannot introduce deadlock in pipes.
A pipe
is left-guarded if it can never output an infinite
sequence of messages to the right channel without inputs from
the left channel. A pipe
is right-guarded if it can never input an infinite
sequence of messages from the left channel without outputting to
the right channel.
A pipe can be modelled as a relation between two sequences
which represent a valid state of the pipe. Chaining pipes is
then equivalent to relational composition. Given
,
if
is left-guarded or
is right-guarded, then:
.
Given pipes
and
,
sending
’s
output to
’s
input is denoted
.
The resulting process is a pipe. The alphabet of such pipe is
.
Of course, if
is valid, then
.
Notice that
.
Notice both pipes can keep infinitely communicating with each
other while not communicating with the external world at all,
which is called livelock. Proving that
requires proving that
is left-guarded or that
is right-guarded.
Given
where both pipes are ready to output data, the right side of the
pipe takes precedence:
Conversely, if both pipes are ready to input data, the left
side of the pipe takes precedence:
If
is ready to input and
is ready to output, the order is unspecified:
Buffers
A buffer is a special type of pipe that outputs the same
sequence it received as input, potentially after some delay.
Given the relational representation of a pipe, a buffer must
obey the following laws:
- A buffer must never stop
- A buffer must be free of livelock
- In all valid states,
.
- In all valid states, if
then the process can’t refuse the communicate on
.
Else, if
then the process can’t refuse to communicate on
It follows that all buffers are left-guarded.
If
and
are buffers, then
and
are also buffers.
is also a buffer if its equal to
).
Traces
A trace is a sequence of events that can be applied in order
to an object. The empty trace
is a valid trace in every object (the shortest possible trace),
and its the default trace when an object didn’t engage on any
event.
The resulting process that occurs after process
engages in trace
is denoted as
.
This expression only makes sense if
.
Notice that
and that
A function
that maps a trace to a trace is strict if
,
and distributive if
.
Notice that if the function is distributive, then its also
strict.
Given a function
that maps an event to an event,
stands for the function that maps a sequence to another sequence
using
on every element. For example,
.
Notice that
is always strict and distributive. Of course,
the mapping operator preserves the sequence length: given
sequence
,
.
Also,
.
Given a process defined as the function
and a set of choices
from its alphabet, its set of traces is defined as
.
Similarly, given a prefix with event
and result
,
.
Finally, given a process composed of choices,
.
The traces of the resulting process after consuming a trace
is all the traces that start with the consumed traces:
.
Events
- :
The catastrophic interrupt event
- :
The process alternation interrupt event
- :
The checkpoint event
- :
Pronounced “success”. Denotes successful termination, and must
be part of the alphabet of the process if used. It can only be
the last event a process engages in.
is invalid if
Chains
A chain is a set of processes
with equal alphabets ordered by the subset operator. It must
hold that
.
The limit (or least upper bound) of a chain
is the process that can consume the traces of all processes in
the chain, defined as
.
The alphabet of the resulting process is
,
which is arbitrary, because all the processes in the chain share
the same alphabet, so the alphabet of any of its elements would
do.
Notice that given a process
and a chain
such that
,
then
and given another process
,
if all the elements of the chain are subsets of
,
then the limit of the chain is also a subset of it:
.
References