SlideShare a Scribd company logo
1 of 22
Download to read offline
Communicating Process Architectures 2009                                                           1
Peter Welch, Herman Roebbers and Tobe Announced (Eds.)
IOS Press, 2009
 c 2009 The authors and IOS Press. All rights reserved.

        CSP as a Domain-Specific Language
         Embedded in Python and Jython
        Sarah Mount 1 , Mohammad Hammoudeh, Sam Wilson and Robert Newman
              School of Computing and I.T., University of Wolverhampton, U.K.

           Abstract. Recently, much discussion has taken place within the Python programming
           community on how best to support concurrent programming. This paper describes a
           new Python library, python-csp, which implements synchronous, message-passing
           concurrency based on Hoare’s Communicating Sequential Processes. Although other
           CSP libraries have been written for Python, python-csp has a number of novel fea-
           tures. The library is implemented both as an object hierarchy and as a domain-specific
           language, meaning that programmers can compose processes and guards using infix
           operators, similar to the original CSP syntax. The language design is intended to be
           idiomatic Python and is therefore quite different to other CSP libraries. python-csp
           targets the CPython interpreter and has variants which reify CSP process as Python
           threads and operating system processes. An equivalent library targets the Jython in-
           terpreter, where CSP processes are reified as Java threads. jython-csp also has Java
           wrappers which allow the library to be used from pure Java programs. We describe
           these aspects of python-csp, together with performance benchmarks and a formal
           analysis of channel synchronisation and choice, using the model checker SPIN.
           Keywords. Communicating Sequential Processes, Python, Dynamic Languages,
           Domain-Specific Languages




Introduction

Python is a lexically scoped, dynamically typed language with object-oriented features,
whose popularity is often said to be due to its ease of use. The rise of multi-core processor
architectures and web applications has turned attention in the Python community to concur-
rency and distributed computing. Recent versions of Python have language-level or standard
library support for coroutines2 , (system) threads3 and process4 management, the latter two
largely in the style of the POSIX thread library. This proliferation of concurrency styles is
somewhat in contrast to the “Zen” of Python [?] which states that “There should be one—and
preferably only one—obvious way to do it.”.
     One reason for adding coroutines (and therefore the ability to use “green” threads) and
operating-system processes is the performance penalty of using Python threads, which is
largely due to the presence of the global interpreter lock (GIL) in the C implementation of the
Python interpreter. The GIL is implemented as an operating system semaphore or condition
variable which is acquired and released in the interpreter every time the running thread blocks

  1
    Corresponding Author: Sarah Mount, School of Computing and I.T., University of Wolverhampton,
Wulfruna St., Wolverhampton, WV1 1SB, U.K.. Tel.: +44 1902 321832; Fax: +44 1902 321478; E-mail:
s.mount@wlv.ac.uk.
  2
    Python PEP 342: Coroutines via Enhanced Generators http://www.python.org/dev/peps/pep-0342/
  3
    http://docs.python.org/library/threading.html#module-threading
  4
    http://docs.python.org/library/multiprocessing.html#module-multiprocessing
2           S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

    for I/O, allowing the operating system to schedule a different thread. A recent presentation
    by Dave Beazley5 contained benchmarks of the following CPU-bound task:
1   def count ( n ):
2           while n > 0:
3                n -= 1

    and found that a parallel execution of the task in threads performed 1.8 times slower than a
    sequential execution and that performance improved if one (of two) CPU cores was disabled.
    These counter-intuitive results are often the basis for developers to call for the GIL to be
    removed. The Python FAQ6 summarises why the GIL is unlikely to be removed from the
    reference implementation of the interpreter, essentially because alternative implementations
    of thread scheduling have caused a performance penalty to single-threaded programs. The
    current solution, therefore, is to provide programmers with alternatives: either to write single-
    threaded code, perhaps using coroutines for cooperative multitasking, or to take advantage
    of multiple cores and use processes and IPC in favour of threads and shared state. A second
    solution is to use another implementation of Python, apart from the CPython interpreter.
    Stackless Python [?] is an implementation which largely avoids the use of the C stack and has
    green threads (called “tasklets”) as part of its standard library. Google’s Unladen Swallow7
    is still in the design phase, but aims to improve on the performance of CPython five-fold and
    intends to eliminate the GIL in its own implementation by 2010.
          This paper describes another alternative, to augment Python with a higher-level abstrac-
    tion for message-passing concurrency, python-csp based on Hoare’s Communicating Se-
    quential Processes [?]. The semantics of CSP are relatively abstract compared with libraries
    such as pthreads and so the underlying implementation of CSP “processes” as either sys-
    tem threads, processes or coroutines is hidden from the user. This means that the user can
    choose an implementation which is suitable for the interpreter in use or the context of the
    application they are developing (for example, processes where a multi-core architecture is
    expected to be used, threads where one is not). Also CSP was designed specifically to help
    avoid well-known problems with models such as shared memory concurrency (such as dead-
    locks and race conditions) and to admit formal reasoning. Both properties assist the user by
    encouraging program correctness. The authors have a particular interest in using Python to
    implement complex tasks requiring coordination between many hosts. The SenSor simulator
    and development tool [?,?] provided facilities for prototyping algorithms and applications for
    wireless sensor networks in pure Python, using shared-memory concurrency. The burden of
    managing explicit locking in an already complex environment made the implementation of
    SenSor difficult. A new version of the tool is currently under development and will be built
    on the python-csp and jython-csp libraries.
          To deal with the different performance characteristics of threads and processes in the cur-
    rent implementations of Python, the python-csp library currently has a number of different
    implementations:
            • The csp.cspprocess module which contains an implementation of python-csp based
              on operating system processes, as managed by the multiprocessing library; and
            • the csp.cspthread module which contains an implementation of python-csp based
              on system threads.
        There is also a version of the library called jython-csp that targets Jython, a version
    of Python which runs on the Java VM. jython-csp uses Java threads (which are also sys-
        5
          http://blip.tv/file/2232410
        6
          http://www.python.org/doc/faq/library/
        7
          http://code.google.com/p/unladenswallow/
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython    3

    tem threads), rather than Python threads. Jython allows the user to mix Java and Python
    code in programs (almost) freely. As such, jython-csp allows users to use any combina-
    tion of Python and Java, including being able to write pure Java programs using wrappers
    for jython-csp types. In general, in this paper we will refer to python-csp, however, the
    syntax and semantics of the libraries can be assumed to be identical, unless stated otherwise.
          The remainder of this paper describes the design and implementation of python-csp
    and jython-csp. Section ?? gives an overview of the design philosophy of the library and
    its syntax and (informal) semantics. Section ?? describes a longer python-csp program and
    gives a discussion of the design patterns used in the implementation. Section ?? begins an
    evaluation of python-csp by describing benchmark results using the Commstime program
    and comparing our work with similar libraries. python-csp and jython-csp have been
    bench-marked against PyCSP [?], another realisation of CSP in Python and JCSP [?], a Java
    library. Section ?? outlines ongoing work on model checking channel synchronisation and
    non-deterministic selection in the python-csp implementation. Section ?? concludes and
    describes future work.


    1. python-csp and jython-csp: Syntax and Semantics

    The design philosophy behind python-csp is to keep the syntax of the library as “Pythonic”
    and familiar to Python programmers as possible. In particular, two things distinguish this li-
    brary from others such as JCSP [?] and PyCSP [?]. Where languages such as Java have strong
    typing and sophisticated control over encapsulation, Python has a dynamic type system, often
    using so-called “duck typing” (which means that an object is said to implement a particular
    type if it shares enough data and operations with the type to be used in the same context as the
    type). Where an author of a Java library might expect users to rely on the compiler to warn of
    semantic errors in the type-checking phase, Python libraries tend to trust the user to manage
    their own encapsulation and use run-time type checking. Although Python is a dynamically
    typed language, the language is helpful in that few, if any, type coercions are implicit. For
    example, where in Java, a programmer could concatenate a String and an int type when
    calling System.out.println, the equivalent expression in Python would raise an exception. In
    general, the Python type system is consistent and this is largely because every Python type
    is reified as an object. Java differs from Python in this respect, as primitive Java types (byte,
    short, int, long, char, float, double, boolean) do not have fields and are not created on the
    heap. In Python, however, all values are (first-class) objects, including functions and classes.
    Importantly for the work described here, operators may be overloaded for new types as each
    Python operator has an equivalent method inherited from the base object, for example:

1   >>> 1 + 2
2   3
3   >>> (1). __add__ (2)
4   3
5   >>> [1] * 3
6   [1 , 1 , 1]
7   >>> ([1]). __mul__ (3)
8   [1 , 1 , 1]
9   >>>
4             S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

Lastly, Python comes with a number of features familiar to users of functional programming
languages such as ML that are becoming common in modern, dynamically typed languages.
These include generators, list comprehensions and higher-order functions.
     CSP [?] contains three fundamental concepts: processes, (synchronous) channel com-
munication and non-deterministic choice. python-csp provides two ways in which the user
may create and use these CSP object types: one method where the user explicitly creates
instances of types defined in the library and calls the methods of those types to make use
of them; and another where users may use syntactic sugar implemented by overriding the
Python built in infix operators. Operator overloading has been designed to be as close to the
original CSP syntax as possible and is as follows:

            Syntax                                            Meaning             CSP equivalent

            P>Q               Sequential composition of processes                                P; Q

             P&Q                  Parallel composition of processes                           P     Q

            c1 | c2                        Non-deterministic choice                         c1      c2

             n∗A                                             Repetition                        n•A

             A∗n                                             Repetition                        n•A

            Skip()        Skip guard, always ready to synchronise                                 Skip



where:
        •   n is an integer;
        •   P and Q are processes;
        •   A is a non-deterministic choice (or ALT); and
        •   c1 and c2 are channels.
        The following sections describe each of the python-csp features in turn.

1.1. python-csp processes

In python-csp a process can be created in two ways: either explicitly by creating an instance
of the CSPProcess class or, more commonly, by using the @process decorator8 . In either case,
a callable object (usually a function) must be created that describes the run-time behaviour
of the process. Listing ?? shows the two ways to create a new process, in this case one which
opens a sensor connected to the USB bus of the host and continuously prints out a transducer
reading every five minutes. Whichever method is used to create the process, P, a special
keyword argument _process must be passed in with a default value. When the process P is
started (by calling its start method) _process is dynamically bound to an object representing
the underlying system thread or process which is the reification of the CSPProcess instance.
This gives the programmer access to values such as the process identifier (PID), or thread
name which may be useful for logging and debugging purposes. When the start methods in
    8
    A “decorator” in Python is a callable object “wrapped” around another callable. For example, the definition
of a function fun decorated with the @mydec decorator will be replaced with fun = mydec(fun).
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython    5

     a CSPProcess object has returned the underlying thread or process will have terminated. Once
     this has happened, accessing the methods or data of the corresponding _process variable will
     raise an exception.
1    # Using the CSPProcess class :
2    def print_rh_reading ():
3          rhsensor = ToradexRH () # Oak temp / humidity sensor
4          rhsensor . open ()
5          while True :
6               data = rhsensor . get_data ()
7               print ’ Humidity %% g : Temp : % gC ’ % data [1:]
8               dingo . platform . gumstix . sleep (60 * 5) # 5 min
9    P = CSPProcess ( print_rh_reading , _process = None )
10   P . start ()
11
12   # Using the @process decorator :
13   @process
14   def print_rh_reading ( _process = None ):
15         rhsensor = ToradexRH () # Oak temp / humidity sensor
16         rhsensor . open ()
17         while True :
18              data = rhsensor . get_data ()
19              print ’ Humidity %% g : Temp : % gC ’ % data [1:]
20              dingo . platform . gumstix . sleep (60 * 5) # 5 min
21   P = print_rh_reading ()
22   P . start ()


                          Listing 1: Two ways to create a python-csp process.


     1.2. python-csp parallel and sequential execution

     CSP processes can be composed either sequentially or in parallel. In sequential execution
     each process starts and terminates before the next in the sequence begins. In parallel execu-
     tion all processes run “at once” and therefore the order of any output they effect cannot be
     guaranteed. Parallel and sequential execution can be implemented in python-csp either by
     instantiating Par and Seq objects or by using the overloaded & or > operators. In general, using
     the overloaded infix operators results in clear, simple code where there are a small number of
     processes. Listing ?? demonstrates sequential and parallel process execution in python-csp.
1    ... def P (n , _process = None ):
2    ...        print n
3    ...
4    >>> # In sequence , using syntactic sugar ...
5    >>> P (1) > P (2)
6         S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

6    1
7    2
8    >>> # In sequence , using objects ...
9    >>> Seq ( P (1) , P (2)). start ()
10   1
11   2
12   >>> # In parallel , using syntactic sugar ...
13   >>> P (1) & P (2)
14   2
15   1
16   >>> # In parallel , using objects ...
17   >>> Par ( P (1) , P (2)). start ()
18   1
19   2


                  Listing 2: Two ways to run processes sequentially and in parallel.


     1.3. python-csp channels

     In CSP communication between processes is achieved via channels. A channel can be thought
     of as a pipe (similar to UNIX pipes) between processes. One process writes data down the
     channel and the other reads. Since channel communication in CSP is synchronous, the writing
     channel can be thought of as offering data which is only actually written to the channel when
     another process is ready to read it. This synchronisation is handled entirely by the language,
     meaning that details such as locking are invisible to the user. Listing ?? shows how channels
     can be used in python-csp.
          In its csp.cspprocess implementation, python-csp uses an operating system pipe to
     transmit serialised data between processes. This has a resource constraint, as operating sys-
     tems limit the number of file descriptors that each process may have open. This means that
     although python-csp programs can create any number of processes (until available memory
     is saturated), a limited number of channels can be created. In practice this is over 600 on a
     Ubuntu Linux PC. To compensate for this, python-csp offers a second implementation of
     channels called FileChannel. A FileChannel object behaves in exactly the same way as any
     other channel, except that it uses files on disk to store data being transferred between pro-
     cesses. Each read or write operation on a FileChannel opens and closes the operating system
     file, meaning that the file is not open for the duration of the application running time. Pro-
     grammers can use FileChannel objects directly, or, if a new Channel object cannot be instan-
     tiated then Channel will instead return a FileChannel object.
          A third class of channel is provided by python-csp, called a NetworkChannel. A
     NetworkChannel transfers data between processes via a socket listener which resides on each
     node in the network for the purpose of distributing channel data. By default when the Python
     csp.cspprocess package is imported, a socket server is started on the host (if one is not al-
     ready running).
1    @process
2    def send_rh_reading ( cout , _process = None ):
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython   7

3          rhsensor = ToradexRH () # Oak temp / humidity sensor
4          timer = TimerGuard ()
5          rhsensor . open ()
6          while True :
7                data = rhsensor . get_data ()
8                cout . send ( ’ Humidity %% g : Temp : % gC ’ % data [1:])
9                timer . sleep (60 * 5) # 5 min
10               guard . read ()                # Synchronise with timer guard .
11
12   @process
13   def simple_sensor ( _process = None ):
14         ch = Channel ()
15         Printer ( ch ) & send_rh_reading ( ch )


                          Listing 3: Two processes communicating via a channel.


     1.4. Non-deterministic selection and guards in python-csp

     Non-deterministic selection (called “select” in JCSP and “ALT” or “ALTing” in occam) is
     an important feature of many process algebras. Select allows a process to choose between a
     number of waiting channel reads, timers or other “guards” which are ready to synchronise. In
     python-csp this is achieved via the select method of any guard type. To use select an Alt
     object must be created and should be passed any number of Guard instances. See Listing ??
     for an example. The select method can be called on the Alt object and will return the value
     returned from the selected guard. To implement a new guard type, users need to subclass the
     Guard class and provide the following methods:

     enable which should attempt to synchronise.
     disable which should roll back from an enable call to the previous state.
     is selectable which should return True if the guard is able to complete a synchronous
          transaction and False otherwise.
     select which should complete the synchronous transaction and return the result (note this
          semantics is slightly different from that found in JCSP, as described by Welch [?],
          where an index to the selected guard in the guard array is returned by select).
     poison which should be used to finalize and delete the current guard and gracefully termi-
          nate any processes connected with it [?,?].
     Since Python has little support for encapsulation, the list of guards inside an Alt object is
     available to any code which has access to the Alt.
1    @process
2    def p r i n t A v a i l a b l e R e a d i n g ( cins , _process = None ):
3          alt = Alt ( cins )
4          while True :
5                print alt . select ()
6    @process
8            S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

7    def s impleS ensorA rray ( _process = None ):
8            chans , procs = [] , []
9            for i in NUMSENSORS :
10                 chans . append ( Channel ())
11                 procs . append ( sendRHReading ( chans [ -1]))
12           procs . append ( p r i n t A v a i l a b l e R e a d i n g ( chans ))
13           Par (* procs ). start ()


           Listing 4: Servicing the next available sensor reading with non-deterministic selection.

          Like many other implementations of CSP, python-csp implements a number of variants
     of non-deterministic selection:

     select enables all guards and either returns the result of calling select on the first available
          guard (if only one becomes available) or randomly chooses an available guard and
          returns the result of its select method. The choice is truly random and determined by
          a random number generator seeded by the urandom device of the host machine.
     priority select enables all guards and, if only one guard becomes available then
          priority_select returns the result of its select method. If more than one guard be-
          comes available the first guard in the list passed to Alt is selected.
     fair select enables all guards and, if only one guard becomes available then fair_select
          returns the result of its select method. Alt objects keep a reference to the guard which
          was selected on the previous invocation of any select method, if there has been such
          an invocation and the guard is still in the guards list. If fair_select is called and more
          than one guard becomes available, then fair_select gives lowest priority to the guard
          which was returned on the previous invocation of any of the select methods. This idiom
          is used to reduce the likelihood of starvation as every guard is guaranteed that no other
          guard will be serviced twice before it is selected.
         There are two forms of syntactic sugar that python-csp implements to assist in dealing
     with Alt objects: a choice operator and a repetition operator. Using the choice operator, users
     may write:
1    result = guard_1 | guard_2 | ... | guard_n

     which is equivalent to:
1    alt = Alt ( guard_1 , guard_2 , ... , guard_n )
2    result = alt . select ()

     To repeatedly select from an Alt object n times, users may write:
1    gen = n * Alt ( guard_1 , guard_2 , ... , guard_n )

     or:
1    gen = Alt ( guard_1 , guard_2 , ... , guard_n ) * n

     this construct returns a generator object which can be iterated over to obtain results from
     Alt.select method calls. Using generators in this way is idiomatic in Python and will be
     familiar to users. The following is a typical use case:
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython   9


1   gen = Alt ( guard_1 , guard_2 , ... , guard_n ) * n
2   while True :
3        ... gen . next () ...

    Each time gen.next() is called within the loop, the select() method of the Alt object is
    called, and its result returned.
         In addition to channel types, python-csp implements two commonly used guard types:
    Skip and TimerGuards. Skip is the guard which is always ready to synchronise. In python-csp
    its select method always returns None, which is the Python null value. TimerGuards are used
    to either suspend a running process (by calling their sleep method) or as part of a synchroni-
    sation where the guard will become selectable after a timer has expired:
1   @process
2   def alarm ( self , cout , _process = None ):
3        alt = Alt ( TimerGuard ())
4        t0 = alt . guard [0]. read ()        # Fetch current time
5        alt . guard [0]. set_alarm (5) # Selectable 5 secs from now
6        alt . select ()
7        duration = guard . read () - t0 # In seconds
8        cout . write ( duration )


    1.5. Graceful process termination in python-csp

    Terminating a parallel program without leaving processes running in deadlock is a difficult
    problem. The most widely implemented solution to this problem was invented by Peter Welch
    [?] and is known as “channel poisoning”. The basic idea is to send a special value down a
    channel which, when read by a process, is then propagated down any other channels known
    to that process before it terminates. In python-csp this can be affected by calling the poison
    method on any guard.
         A common idiom in python-csp, especially where producer / consumer patterns are
    implemented, is this:
1   alt = Alt (* channels )
2   for i in xrange ( len ( channels )):
3        alt . select ()

    Here, it is intended that each guard in channels be selected exactly once. Once a guard has
    been selected its associated writer process(es) will have finished its computation and ter-
    minate. In order to support this idiom efficiently, python-csp implements a method called
    poison on Alt objects which serves to poison the writer process(es) attached to the last se-
    lected guard and remove that guard from the list, used as follows:
1   a = Alt (* channels )
2   for i in xrange ( len ( channels )):
3        a . select ()
4        a . poison ()
10          S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

    By shortening the list of guards less synchronisation is required on each iteration of the for
    loop, reducing the computational effort required by the select method.

    1.6. Built-in processes and channels

    python-csp comes with a number of built-in processes and channels, aimed to speed de-
    velopment. This includes all of the names defined in the JCSP “plugnplay” library. In addi-
    tion to these and other built-in processes and guards, python-csp comes with analogues of
    every unary and binary operator in Python. For example, the Plus process reads two values
    from channels and then writes the addition of those values to an output channel. An example
    implementation9 of this might be:
1   @process
2   def Plus ( cin1 , cin2 , cout , _process = None ):
3            while True :
4                in1 = cin1 . read ()
5                in2 = cin2 . read ()
6                cout . write ( in1 + in2 )
7            return


                         Listing 5: A simple definition of the built-in Plus process.


    1.7. jython-csp implementation and integration with pure Java

    jython-csp is a development of python-csp for integration with Jython. Jython has sim-
    ilar semantics as Python but uses the Java runtime environment (JRE) which allows access
    to the large number of Java libraries, such as Swing, which are useful, platform-independent
    and well optimised. jython-csp has similar workings to the initial python-csp with the
    ability to utilise any class from the standard Java and Python class libraries. jython-csp
    utilises Java threads and would be expected to perform similarly to other CSP implementa-
    tions based on Java threads, such as JCSP (e.g. [?]). A comparison between jython-csp and
    python-csp implementations of the Monte Carlo approximation to π is shown in Table ??.

                  Table 1. Results of testing Java threads against Python threads and OS processes.
                      Thread Library                  Running time of π approximation (seconds)
                      jython-csp (Java Threads)       26.49
                      python-csp (Python Threads)     12.08
                      python-csp (OS Processes)       9.59


         As we shall see in Section ?? the JCSP library performs channel communication very
    efficiently, so one might expect that jython-csp would also execute quickly. A speculation
    as to why jython-csp (using Java threads) performs poorly compared to the other CSP
    implementations is a slow Java method dispatch within Jython.
         9
       In fact, these processes are implemented slightly differently, taking advantage of Python’s support for re-
    flection. Generic functions called _applybinop and _applyunaryop are implemented, then Plus may be de-
    fined simply as Plus = _applybinop(operator.__add__). The production version of this code is slightly
    more complex as it allows for documentation for each process to be provided whenever _applybinop and
    _applyunaryop are called.
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython   11

    In addition to the modification of the threading library used jython-csp also takes ad-
vantage of Java locks and semaphores from the java.util.concurrent package. jython-csp
has no dependency on non standard packages; the library will work with any JRE which is
compatible with Jython 2.5.0final.

1.8. Java-csp

Java-csp is the integration of jython-csp with Java to allow Java applications to utilise the
flexibility of jython-csp.
     The Java CSP implementation attempts to emulate the built in Java thread library
(java.lang.Thread) with a familiar API. As with Java threads there are two ways to use
threads in an application:
       • By extending the Thread class and overwriting the run method; or
       • By implementing the Runnable interface.
       The Java csp implementation has a similar usage:
       • Extending the JavaCspProcess and overwriting the target method; or
       • Implementing the JavaCspProcessInterface interface.
     jython-csp and python-csp uses the pickle library as a means of serialising data down
a channel. Pickle takes a Python/Jython object and returns a sequence of bytes; this approach
only works on Python/Jython object and is unsuitable for native Java objects. As a solution
java-csp implements a wrapped version of Java object serialization which allows Jython to
write pure Java objects, which implement the Serializable interface, to a channel, in addition
to this, Python/Jython objects can be written down a channel if they extend the PyObject class.


2. Mandelbrot generator: an example python-csp program

2.1. Mandelbrot generator

Listing ?? shows a longer example of a python-csp program as an illustration of typical cod-
ing style. The program generates an image of a Mandelbrot set which is displayed on screen
using the PyGame library10 (typically used for implementing simple, 2D arcade games).
     The Mandelbrot set is an interesting example, since it is embarrassingly parallel – i.e.
each pixel of the set can be calculated independently of the others. However, calculating
each pixel of a large image in a separate process may be a false economy. Since channel
communication is likely to be an expensive part, the resulting code is likely to be I/O bound.
The code in Listing ?? is structured in such a way that each column in the image is generated
by a separate “producer” process. Columns are stored in memory as a list of RGB tuples
which are then written to a channel shared by the individual producer process and a single
“consumer” process. The main work of the consumer is to read each image column via an
Alt object and write it to the display surface.
     This producer / consumer architecture is common to many parallel and distributed pro-
grams. It it not necessarily, however, the most efficient structure for this program. Since some
areas of the set are essentially flat and so simple to generate, many producer processes are
likely to finish their computations early and spend much of their time waiting to be selected
by the consumer. If this is the case, it may be better to use a “farmer” process to task a smaller
number of “worker” processes with generating a small portion of the image, and then re-task
each worker after it has communicated its results to the farmer. Practically, if efficiency is
  10
       http://www.pygame.org
12        S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

     an important concern, these options need to be prototyped and carefully profiled in order to
     determine the most appropriate solution to a given problem.
1    from csp . cspprocess import *
2    @process
3    def mandelbrot ( xcoord , ( width , height ) , cout ,
4                        acorn = -2.0 , bcorn = -1.250 , _process = None ):
5         # Generate image data for column xcoord ...
6         cout . write (( xcoord , imgcolumn ))
7         _process . _terminate ()
8    @process
9    def consume ( IMSIZE , filename , cins , _process = None ):
10        # Create initial pixel data .
11        pixmap = Numeric . zeros (( IMSIZE [0] , IMSIZE [1] , 3))
12        pygame . init ()
13        screen = pygame . display . set_mode (( IMSIZE [0] , IMSIZE [1]) , 0)
14        # Wait on channel data .
15        alt = ALT (* cins )
16        for i in range ( len ( cins )):
17                   xcoord , column = alt . select ()
18              alt . poison () # Remove last selected guard and producer .
19              # Update column of blit buffer
20              pixmap [ xcoord ] = column
21              # Update image on screen .
22              pygame . surfarray . blit_array ( screen , pixmap )
23   def main ( IMSIZE , filename ):
24        channels , processes = [] , []
25        for x in range ( IMSIZE [0]): # Producer + channel per column .
26              channels . append ( Channel ())
27              processes . append ( mandelbrot (x , IMSIZE , channels [ x ]))
28        processes . insert (0 , consume ( IMSIZE , filename , channels ))
29        mandel = PAR (* processes )
30        mandel . start ()


                         Listing 6: Mandelbrot set in python-csp (abridged).

          The worker/ farmer architecture shows an improvement in performance over the pro-
     ducer / consumer architecture. The code in Listing ?? is structured in such a way that each
     column in the image is computed by a single process. Initially a set of workers are created
     and seeded with the value of the column number, the pixel data for that column is generated
     then written to a channel. When the data has been read, the “farmer” then assigns a new col-
     umn for the worker to compute, if there are no remaining columns to be generated the farmer
     will write a terminating value and the worker will terminate, this is required to instruct the
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython   13

     “worker” that there are no more tasks to be performed. The consumer has the same function
     as before although with a smaller set of channels to choose from. Workers which have com-
     pleted their assigned values have a shorter amount of time to wait until the Alt object selects
     them.

1    @process
2    def mandelbrot ( xcoord , ( width , height ) , cout ,
3                          acorn = -2.0 , bcorn = -1.250 , _process = None ):
4            # Generate image data for column xcoord ...
5            cout . write (( xcoord , imgcolumn ))
6            xcoord = cout . read ()
7            if xcoord == -1:
8                 _process . _terminate ()
9    @process
10   def consume ( IMSIZE , filename , cins , _process = None ):
11           global SOFAR
12           # Create initial pixel data
13           pixmap = Numeric . zeros (( IMSIZE [0] , IMSIZE [1] , 3))
14           pygame . init ()
15           screen = pygame . display . set_mode (( IMSIZE [0] , IMSIZE [1]) , 0)
16           # Wait on channel data
17           alt = Alt (* cins )
18           for i in range ( IMSIZE [0]):
19               xcoord , column = alt . pri_select ()
20               # Update column of blit buffer
21                pixmap [ xcoord ] = column
22               # Update image on screen .
23                pygame . surfarray . blit_array ( screen , pixmap )
24               if SOFAR < IMSIZE [0]:
25                     alt . last_selected . write ( SOFAR )
26                     SOFAR = SOFAR + 1
27                else :
28                     alt . last_selected . write ( -1)


     Listing 7: Mandelbrot set in python-csp (abridged) using the “farmer” /“worker” architec-
     ture.


          The improvement in performance can been seen in Figure ??, using a smaller number of
     processes reduces the run time of the program.
          The graph shows a linear characteristic, which would be expected as the select method
     in Alt is O(n).
14         S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython




 Figure 1. Run times of “farmer” / “worker” Mandelbrot program with different numbers of CSP processes.

3. Performance evaluation and comparison to related work

The Commstime benchmark was originally implemented in occam by Peter Welch at the
University of Kent at Canterbury and has since become the de facto benchmark for CSP
implementations such as occam-π [?], JCSP [?] and PyCSP [?].
     Table ?? shows results of running the Commstime benchmark on JCSP version 1.1rc4,
PyCSP version 0.6.0 and python-csp. To obtain fair results the implementation of Comm-
stime used in this study was taken directly from the PyCSP distribution, with only syntactic
changes made to ensure that tests run correctly and are fairly comparable. In each case, the
type of “process” used has been varied and the default channel implementation has been used.
In the case of the python-csp channels are reified as UNIX pipes. The JCSP implementation
uses the One2OneChannelInt class. The PyCSP version uses the default PyCSP Channel class
for each process type. All tests were run on an Intel Pentium dual-core 1.73GHz CPU and
1GB RAM, running Ubuntu 9.04 (Jaunty Jackalope) with Linux kernel 2.6.28-11-generic.
Version 2.6.2 of the CPython interpreter was used along with Sun Java(TM) SE Runtime
Environment (build 1.6.0 13-b03) and Jython 2.50.
Table 2. Results of testing various CSP libraries against the Commstime benchmark. In each case the default
Channel class is used.
                 CSP               Process           min      max       mean    standard
                 implementation    reification        (µ s)    (µ s)     (µ s)   deviation
                 JCSP              JVM thread          15      29       23.8      4.29
                 PyCSP             OS process       195.25   394.97    330.34     75.82
                 PyCSP             Python thread    158.46   311.2      292.2     47.21
                 PyCSP             Greenlet          24.14   25.37      24.41     0.36
                 python-csp        OS process         67.6   155.97    116.75     35.53
                 python-csp        Python thread    203.05   253.56    225.77     17.51
                 jython-csp        JVM thread       135.05    233       157.8     30.78

     The results show that channel operations in jython-csp are faster than channel opera-
tions between python-csp objects when reified as threads, but slower than the thread-based
version of python-csp. This is a surprising result, as Java threads are better optimised than
Python threads (because of the way the Python GIL is implemented) and, as the results for
JCSP show, it is possible to implement CSP channels very efficiently in pure Java. The loss
of performance is likely to be due to the way in which methods are invoked in Jython. Rather
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython    15

than all compiling Jython code directly to Java bytecode (as was possible when Jython sup-
ported the jythonc tool), Jython wraps Python objects in Java at compile time and executes
pure Python code in and instance of a Python interpreter. Mixing Python and Java code, as
the jython-csp library does, can therefore result in poor performance. It may be possible
to ameliorate these problems by implemented more of the jython-csp library in pure Java
code. It is also possible that future versions of Jython will improve the performance of method
invocation and/or provide a method of compiling Python code directly to Java bytecode.
     The difference between the python-csp and PyCSP libraries is also surprising.
python-csp implements channel synchronisation in a simple manner, with two semaphores
protecting each channel, and two reentrant locks to guard against conflicts between multiple
readers and/or writers. PyCSP has a very different architecture and synchronisation strategy
which may account for the difference in performance. More detailed profiling of the two
libraries, together with the completion of the model checking work described in Section (to
ensure that python-csp is not simply faster because it is somehow incorrect) will form part
of our future work.
3.1. Related work
There are some differences between the implementation of python-csp and other realisa-
tions of CSP, such as occam-π, JCSP [?] and PyCSP [?]. In particular, any channel object
may have multiple readers and writers. There are no separate channel types such as JCSPs
One2OneChannel. This reflects the simplicity that Python programmers are used to and the
PEP20 [?] maxim that ““There should be one—and preferably only one—obvious way to
do it.”. Also, when a Channel object (or variant of such) is instantiated, the instance itself is
returned to the caller. In contrast, other systems return a “reader” and “writer” object, often
implemented as the read and write method of the underlying channel. This is similar to the
implementation of operating system pipes in many libraries, where a reader and writer to the
pipe is returned by a library call, rather than an abstraction of the pipe. The authors of these
other CSP realisations would argue that their design is less likely to be error prone and that
they are protecting the error-prone programmer from inadvertently reading from a channel
that is intended to be a “output” channel to the given process or writing to a channel that is
intended to be an “input” to the process. However, python-csp comes with strong tool sup-
port which may ameliorate some of these potential errors, and the profusion of channel types
in some systems may confuse rather than simplify. Similarly, Alt.select methods return the
value read by a guard rather than the index to the selected guard (as in JCSP) or a reference to
the selected guard (PyCSP). The last guard selected is stored in the field Alt.last_selected
and so is available to users.
     Some pragmatic concessions to the purity of python-csp have been made. In particular,
the three default channel types (Channel, FileChannel and NetworkChannel) have very different
performance and failure characteristics and so are implemented separately and conspicuously
to the user. The chances of a network socket failing, and the potential causes of such a fail-
ure, differ greatly from that of an operating system pipe. Equally, a process which times-out
waiting for a channel read will need to wait considerably longer for a read on a FileChannel
than a Channel. These are non-trivial differences in semantics and it seems beneficial to make
them explicit.

4. Correctness of synchronisation in python-csp
4.1. SPIN
To verify the correctness of synchronisation in python-csp, a formal model was built using
high level language to specify systems descriptions, called Promela (a PROcess MEta LAn-
16        S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

    guage). This choice is motivated by convenience since a large number of Promela models are
    available in the public domain and some of the features of the SPIN (Simple Promela INter-
    preter) tool environment [?], which interprets Promela, greatly facilitate our model analysis.
    Given a model system specified in Promela, SPIN can generate a c program that performs a
    fast exhaustive verification of the system state space. In addition, SPIN can perform random or
    guided simulations of the system’s execution following one possible execution path through
    the system and showing the resulting execution trace to the user. During simulations and ver-
    ifications SPIN checks for the presence of deadlocks, livelocks, starvation, race conditions,
    unspecified receptions, and unexecutable code. As a simulator, SPIN allows for rapid proto-
    typing of systems by visualising communications between different entities/processes. The
    verifier can be used to prove the correctness of system invariants and to reveal serious design
    problems in the model. Finally, SPIN supports the verification of linear time temporal con-
    straints; either with Promela never-claims/assertions or by directly formulating the constraints
    in temporal logic.

    4.2. Promela

    Promela   is a non-deterministic language, loosely based on Dijkstra’s guarded command lan-
    guage notation and borrowing the notation for i/o operations from Hoare’s CSP language.
    Promela provides all of the necessary features to trace logical design errors in distributed con-
    current algorithms such as parallel and asynchronous composition of concurrent processes,
    guarded and non-deterministic control structures, communication channels, and sending and
    receiving primitives.
          The syntax of Promela is c-like. Promela models consist of processes, message channels,
    and variables. Processes (proctype) are global objects that represent the concurrent entities
    of a distributed system. Message channels (chan) and data objects define the environment in
    which the processes run. Statements are either enabled or blocked. Blocking is a primary
    mechanism to enforce synchronising communication between processes. The sending or re-
    ceiving process blocks until the system transfers the message. If a statement is blocked, ex-
    ecution at that point halts until the statement becomes enabled or control can be transferred
    outside the scope of the statement by explicit goto. If this statement afterwards becomes en-
    abled again, execution may continue at that point. The initialisation process init is often
    used to begin the main of the code to model the global system process. It prepares the ini-
    tial state of the system by initialising global variables and instantiating the appropriate pro-
    cesses. It should be employed to activate simultaneously (run) process-instances of agents
    and potentially the environment.

    4.3. Model checking results

    The model was divided into the three primary processes: the ALT, the read, and the write. Syn-
    chronisation was modelled by semaphores for several readers and several writers in Promela.
    Process type declarations consist of the keyword proctype, followed by the name of the pro-
    cess type, and an argument list. For example, N instances of the process type read are defined
    as follows:
1   active [ N ] proctype reader ()
2   {          ( rlock )   -> rlock = false ;
3              read ();
4              rlock = true ;
5              skip }
6
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython   17

7    inline read ()
8    {         lock ( listlock );
9              if
10             :: is_selectable [0] && waiting [0] ->
11                         do
12                         :: ( rlock ) -> rlock = false ; /* obtain rlock */
13                                    atomic { /* wait ( sem ) acquire available */
14                                     available > 0 -> available - -;}
15                         c_r ? msg ; /* get data from pipe critical section */
16                         taken ++; /* release taken */
17                         rlock = true ; /* release rlock */
18                         od ;
19                         waiting [0] = 0
20                         enable (0);
21             :: else
22             fi ;
23             unlock ( listlock )}


          The reader process first obtains the rlock flag to protect from races between multiple
     readers, then blocks until an item becomes available in the channel, then gets the item from
     the pipe (in the critical section), then announces the item has been read, then releases the
     rlock flag.
          The writer process is declared in a similar style to the read process. The writer process
     first obtains the wlock flag to protect from races between multiple writers, then places an item
     in the channel, then makes the item available for the reader, then blocks until the item has
     been read, and finally releases the wlock.

1    active [ N ] proctype writer ()
2    {         ( wlock ) -> wlock = false ;
3              write ();
4              printf ( " % d finished writing  n " , _pid );
5              wlock = true ;
6              skip }
7
8    inline write ( block )
9    {         if
10             :: atomic { select -> printf ( " 1 st time acquire  n " ); } ->
11                         goto endd
12             :: else
13             fi ;
14             if
15             :: ! block -> goto endd
18        S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

16             :: else
17             fi ;
18             semqueue ();
19             do
20             :: skip ->
21                         waiting [ _pid ] = 1;
22                         if
23                         :: atomic { select -> printf ( " not 1 st time acquire  n " );
24             } ->
25                                    break
26                         :: else
27                         fi ;
28                         disable ( semaenabled ())
29             od ;
30             semdequeue ();
31   endd :
32             do
33             :: ( wlock ) -> wlock = false ; /* obtain wlock */
34                         s_c ! msg ; /* place item in pipe critical section */
35                         available ++; /* release available */
36                         atomic { taken > 0;
37                                    taken -- /* acquire taken */}
38                         wlock = true ; /* release wlock */
39             od ;
40             assert (! block || selected [ _pid ]);
41             assert selected [ _pid ];
42             assert ! waiting [ _pid ];
43             printf ( " % d done  n " , _pid );}

          The channel algorithm used in this model is defined as:
1    chan s_c = [0] of { mtype }; /* rendezvous channel */
2    chan c_r = [0] of { mtype };
3
4    active proctype pipe ()
5    {         mtype m ;
6              do
7              :: s_c ? m -> c_r ! m
8              od }

          The first two statements declare sc and cr to be channels. These will provide commu-
     nication to write into or read from the pipe, with no buffering capacity (i.e., communication
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython   19

     will be via rendezvous) that carries messages consisting of a byte (mtype). The body of the
     do-loop retrieves the received message and stores it into the local variable m on the receiver
     side. The data is always stored in empty channels and is always retrieved from full channels.
          The ALT process manages three different arrays to store and change the status of various
     read and write processes. Each process can be in one of the following states: waiting[N]: the
     process is ready to synchronise disabled[N]: the process should not attempt to synchronise
     and should roll back from an enable call to the previous state is_selectable[N]: is true if the
     guard is able to complete a synchronous transaction selected[N]: the process should complete
     a synchronous transaction (write-read) The process can only read and change its state in
     the array after it completes a transaction such as read or write. The ALT process can also
     change the state of various processes. For example, the ALT process can select two processes to
     synchronise and disable all other processes. This state space management implementation is
     simpler than exchanging messages between the ALT and read or write processes to set or read
     processes states that is required to accomplish a read-write synchronisation transaction. The
     exchange of state messages makes the model complex and requires careful synchronisation.
     Nevertheless, since more than one process can access the array a listlock semaphore was
     implemented to prevent races between multiple processes.

1    inline lock ( x )
2    {          atomic { x == 0; x = 1 }}
3
4    inline unlock ( x )
5    {          assert x ==1; x = 0}
6
7    lock ( listlock );
8    unlock ( listlock );

          The ALT process pushes the selectable process, ready to complete a synchronisation trans-
     action, into a queue before the synchronisation starts (dequeue). This implementation will
     make any future improvements or modifications to the nondeterministic selection procedure
     easy to model. For example, the ALT can use various nondeterministic selection methods such
     as priority select or fair select.

1    inline semqueue ()
2    {         lock ( listlock );
3               assert ! is_selectable [ _pid ];
4               is_selectable [ _pid ] = 1;
5               unlock ( listlock )}
6
7    inline semdequeue ()
8    {         lock ( listlock );
9               assert is_selectable [ _pid ];
10              is_selectable [ _pid ] = 0;
11              waiting [ _pid ] = 0;
12              unlock ( listlock )}
20        S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

         Firstly, the model was run in SPIN random simulation mode. SPIN simulator enables users
    to gain early feedback on their system models that helps in the development of the designers
    understanding of the design space before they advance in any formal analysis. However, SPIN
    provides a limited form of support for verification in terms of assertion checking, i.e. the
    checking of local and global system properties during simulation runs. For example, a process
    called monitor was devoted to assert that a read process will not be executed if the buffer
    is empty and the buffer can not be overwritten by write process before the read process is
    executed.
1   proctype monitor ()
2   {         do
3             :: assert ( taken <2) ;
4             :: assert ( available <2);
5             od }




         Figure 2. Message sequence chart of SPIN model checker showing two readers and two writers.

         Figure ?? shows the Message Sequence Chart (MSC) Panel. Each process is associated
    with a vertical line where the ”start of time” corresponds to the top of the MSC moving down
    with the vertical distance represents the relative time between different temporal events. The
    message passing is represented by the relative ordering of arrows between process execution
    lines.
         SPIN verification mode is used to verify liveness and safety properties like deadlock de-
    tection, invariants or code reachability. Verification parameters are set to enable check for
    ”invalid endstates” in the model.
1   spin -a py - csp . p
2   pcc - DSAFETY - DREACH - D M E M L I M =       500 -O pan pan . c
3   pan -i
4   rm pan .* pan
S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython            21

   The verification output does not show any output referring to ”invalid end states” which
means that the verification has passed.


5. Conclusions and future work

python-csp provides a “Pythonic” library for the structuring of concurrent programs in a
CSP style. This provides an alternative to the event-driven style which has become preva-
lent with the increasing popularity of object oriented methods. python-csp realises the
three fundamental concepts of CSP, processes, synchronous channel communication and non-
determnistic choice, for use both explicitly and with appropriate syntactic sugar to provide
program texts with much more of the ’look and feel’ of CSP.
     python-csp has been realised as a number of distinct realisations. One notable imple-
mentation is jython-csp, which, as a result of Jython’s reliance on the Java Virtual Machine,
yields a platform independent implementation.
     As an example of a real program, parallelised using python-csp, the Mandelbrot gener-
ator has been presented. Both a producer/consumer and worker/farmer implementation have
been described, and the worker/farmer shows a linear performance relationship with number
of processes used (running on a dual-core computer).
     The correctness of channel synchronisation in python-csp has been demonstrated using
a model checker. Future work will include a study of the correctness of non-deterministic
selection in python-csp.
     Evaluation of the performance of python-csp shows that it performs slightly faster than
equivalent implementations of PyCSP (significantly faster for the OS process version).
     The motivation for the constriction of python-csp was to provide a syntactically nat-
ural and semantically robust framework for the design and implementation of large scale,
distributed, parallel systems, in particular wireless sensor networks. It is hoped that such
systems will one day be grounded in a secure theory of communication and concurrency.
python-csp has provided such a framework, but is so far limited to a shared memory, sin-
gle machine implementation. The next stages in this work are to extend the synchronised
communications to operate over inter-machine communications links. In some ways, CSP
communications, being already modelled on a ’channel’, are ideal for such a purpose. On
the other hand, real communications channels, particularly wireless ones, have quite different
characteristics from the instantaneous and reliable CSP channel. Finding efficient means for
duplicating the semantics of the CSP channel using real communications remains a challenge
for the authors.


Acknowledgements

The authors wish to acknowledge the Nuffield Foundation’s support for this research through
an Undergraduate Research Bursary (URB/37018), which supported the work of the third
author.


References

 [1] Tim Peters. PEP20 the zen of python. http://www.python.org/dev/peps/pep-0020/, August 2004.
 [2] Christian Tismer. Continuations and stackless python or ”how to change a paradigm of an existing pro-
     gram”. In In Proceedings of the 8th International Python Conference, January 2000.
 [3] C.A.R. Hoare. Communicating Sequential Processes. Prentice-Hall, London, 1985. ISBN: 0-131-53271-
     5.
22         S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython

 [4] S.N.I. Mount, R.M. Newman, and E.I. Gaura. A simulation tool for system services in ad-hoc wireless
     sensor networks. In In Proceedings of NSTI Nanotechnology Conference and Trade Show (Nanotech’05),
     volume 3, pages 423–426, Anaheim, California, USA, May 2005.
 [5] S. Mount, R.M. Newman, E. Gaura, and J. Kemp. Sensor: an algorithmic simulator for wireless sensor
     networks. In In Proceedings of Eurosensors 20, volume II, pages 400–411, Gothenburg, Sweden, 2006.
 [6] John Markus Bjørndalen, Brian Vinter, and Otto J. Anshus. PyCSP - Communicating Sequential Processes
     for Python. In Alistair A. McEwan, Wilson Ifill, and Peter H. Welch, editors, Communicating Process
     Architectures 2007, pages 229–248, jul 2007.
 [7] P.H.Welch. Process Oriented Design for Java: Concurrency for All. In H.R.Arabnia, editor, Proceed-
     ings of the International Conference on Parallel and Distributed Processing Techniques and Applications
     (PDPTA’2000), volume 1, pages 51–57. CSREA, CSREA Press, June 2000.
 [8] N.C.C. Brown and P.H. Welch. An introduction to the Kent C++CSP library. In J.F. Broenink and G.H.
     Hilderink, editors, Communicating Process Architectures 2003, volume 61 of Concurrent Systems Engi-
     neering Series, pages 139–156, Amsterdam, The Netherlands, September 2003. IOS Press.
 [9] Bernhard H. C. Sputh and Alastair R. Allen. Jcsp-poison: Safe termination of csp process networks. In
     Jan F. Broenink, Herman W. Roebbers, Johan P. E. Sunter, Peter H. Welch, and David C. Wood, editors,
     CPA, volume 63 of Concurrent Systems Engineering Series, pages 71–107. IOS Press, 2005.
[10] P.H. Welch. Graceful Termination – Graceful Resetting. In Applying Transputer-Based Parallel Machines,
     Proceedings of OUG 10, pages 310–317, Enschede, Netherlands, April 1989. Occam User Group, IOS
     Press, Netherlands. ISBN 90 5199 007 3.
[11] Peter H. Welch and Fred R.M. Barnes. Communicating mobile processes: introducing occam-pi. In
     A.E. Abdallah, C.B. Jones, and J.W. Sanders, editors, 25 Years of CSP, volume 3525 of Lecture Notes in
     Computer Science, pages 175–210. Springer Verlag, April 2005.
[12] Gerard J. Holzmann. The model checker SPIN. IEEE Transactions on Software Engineering, 23:279–295,
     1997.

More Related Content

What's hot

Introduction to MPI
Introduction to MPI Introduction to MPI
Introduction to MPI Hanif Durad
 
XMPP - Introduction And LAS Implementation (Presentation)
XMPP - Introduction And LAS  Implementation (Presentation)XMPP - Introduction And LAS  Implementation (Presentation)
XMPP - Introduction And LAS Implementation (Presentation)Ralf Klamma
 
Message Passing Interface (MPI)-A means of machine communication
Message Passing Interface (MPI)-A means of machine communicationMessage Passing Interface (MPI)-A means of machine communication
Message Passing Interface (MPI)-A means of machine communicationHimanshi Kathuria
 
Intro to MPI
Intro to MPIIntro to MPI
Intro to MPIjbp4444
 
PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...
PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...
PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...RuleML
 
Pauls klein 2011-lm_paper(3)
Pauls klein 2011-lm_paper(3)Pauls klein 2011-lm_paper(3)
Pauls klein 2011-lm_paper(3)Red Over
 
Hetergeneous Compute with Standards Based OFI/MPI/OpenMP Programming
Hetergeneous Compute with Standards Based OFI/MPI/OpenMP ProgrammingHetergeneous Compute with Standards Based OFI/MPI/OpenMP Programming
Hetergeneous Compute with Standards Based OFI/MPI/OpenMP ProgrammingIntel® Software
 
Point-to-Point Communicationsin MPI
Point-to-Point Communicationsin MPIPoint-to-Point Communicationsin MPI
Point-to-Point Communicationsin MPIHanif Durad
 
Parallel programming using MPI
Parallel programming using MPIParallel programming using MPI
Parallel programming using MPIAjit Nayak
 
MPI Presentation
MPI PresentationMPI Presentation
MPI PresentationTayfun Sen
 
DEF CON 27 - JEFF DILEO - evil e bpf in depth
DEF CON 27 - JEFF DILEO - evil e bpf in depthDEF CON 27 - JEFF DILEO - evil e bpf in depth
DEF CON 27 - JEFF DILEO - evil e bpf in depthFelipe Prado
 
A novel approach for clone group mapping
A novel approach for clone group mappingA novel approach for clone group mapping
A novel approach for clone group mappingijseajournal
 
WEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTHWEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTHBhavsingh Maloth
 

What's hot (20)

Mpi Java
Mpi JavaMpi Java
Mpi Java
 
My ppt hpc u4
My ppt hpc u4My ppt hpc u4
My ppt hpc u4
 
Introduction to MPI
Introduction to MPI Introduction to MPI
Introduction to MPI
 
XMPP - Introduction And LAS Implementation (Presentation)
XMPP - Introduction And LAS  Implementation (Presentation)XMPP - Introduction And LAS  Implementation (Presentation)
XMPP - Introduction And LAS Implementation (Presentation)
 
Mpi Test Suite Multi Threaded
Mpi Test Suite Multi ThreadedMpi Test Suite Multi Threaded
Mpi Test Suite Multi Threaded
 
Message Passing Interface (MPI)-A means of machine communication
Message Passing Interface (MPI)-A means of machine communicationMessage Passing Interface (MPI)-A means of machine communication
Message Passing Interface (MPI)-A means of machine communication
 
Open MPI
Open MPIOpen MPI
Open MPI
 
Intro to MPI
Intro to MPIIntro to MPI
Intro to MPI
 
PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...
PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...
PSOA2TPTP: A Reference Translator for Interoperating PSOA RuleML with TPTP Re...
 
Pauls klein 2011-lm_paper(3)
Pauls klein 2011-lm_paper(3)Pauls klein 2011-lm_paper(3)
Pauls klein 2011-lm_paper(3)
 
Research paper on python by Rj
Research paper on python by RjResearch paper on python by Rj
Research paper on python by Rj
 
Tools4BPEL4Chor
Tools4BPEL4ChorTools4BPEL4Chor
Tools4BPEL4Chor
 
Hetergeneous Compute with Standards Based OFI/MPI/OpenMP Programming
Hetergeneous Compute with Standards Based OFI/MPI/OpenMP ProgrammingHetergeneous Compute with Standards Based OFI/MPI/OpenMP Programming
Hetergeneous Compute with Standards Based OFI/MPI/OpenMP Programming
 
Point-to-Point Communicationsin MPI
Point-to-Point Communicationsin MPIPoint-to-Point Communicationsin MPI
Point-to-Point Communicationsin MPI
 
Introduction to MPI
Introduction to MPIIntroduction to MPI
Introduction to MPI
 
Parallel programming using MPI
Parallel programming using MPIParallel programming using MPI
Parallel programming using MPI
 
MPI Presentation
MPI PresentationMPI Presentation
MPI Presentation
 
DEF CON 27 - JEFF DILEO - evil e bpf in depth
DEF CON 27 - JEFF DILEO - evil e bpf in depthDEF CON 27 - JEFF DILEO - evil e bpf in depth
DEF CON 27 - JEFF DILEO - evil e bpf in depth
 
A novel approach for clone group mapping
A novel approach for clone group mappingA novel approach for clone group mapping
A novel approach for clone group mapping
 
WEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTHWEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTH
WEB PROGRAMMING UNIT VIII BY BHAVSINGH MALOTH
 

Viewers also liked

6.opening sequence
6.opening sequence6.opening sequence
6.opening sequencegia1995
 
Matilde's civilization project 5M
Matilde's civilization project 5MMatilde's civilization project 5M
Matilde's civilization project 5MgsbSS
 
Marketing management market segmentation
Marketing management market segmentationMarketing management market segmentation
Marketing management market segmentationIam Varien
 
Entypo ekpaidefsis kai katartisis
Entypo ekpaidefsis kai katartisisEntypo ekpaidefsis kai katartisis
Entypo ekpaidefsis kai katartisisEleni Papadopoulou
 
ьрплплбплр
ьрплплбплрьрплплбплр
ьрплплбплрleneth6
 
HOLA in ENGLISH
HOLA in ENGLISHHOLA in ENGLISH
HOLA in ENGLISHdearl1
 
Course 2 week 6 lesson 10
Course 2 week 6 lesson 10Course 2 week 6 lesson 10
Course 2 week 6 lesson 10Joe Mellin
 
MDML@FCPL ILF 2013 Presentation
MDML@FCPL ILF 2013 PresentationMDML@FCPL ILF 2013 Presentation
MDML@FCPL ILF 2013 PresentationJonathan Gaskill
 
портфолио Шликова В.В.
портфолио Шликова В.В.портфолио Шликова В.В.
портфолио Шликова В.В.TheShkola21
 
Evoluzione della società umana
Evoluzione della società umana Evoluzione della società umana
Evoluzione della società umana Lorenzo Dodi
 

Viewers also liked (20)

6.opening sequence
6.opening sequence6.opening sequence
6.opening sequence
 
Matilde's civilization project 5M
Matilde's civilization project 5MMatilde's civilization project 5M
Matilde's civilization project 5M
 
Project
ProjectProject
Project
 
Marketing management market segmentation
Marketing management market segmentationMarketing management market segmentation
Marketing management market segmentation
 
Entypo ekpaidefsis kai katartisis
Entypo ekpaidefsis kai katartisisEntypo ekpaidefsis kai katartisis
Entypo ekpaidefsis kai katartisis
 
Deepak ppt
Deepak pptDeepak ppt
Deepak ppt
 
ьрплплбплр
ьрплплбплрьрплплбплр
ьрплплбплр
 
HOLA in ENGLISH
HOLA in ENGLISHHOLA in ENGLISH
HOLA in ENGLISH
 
Course 2 week 6 lesson 10
Course 2 week 6 lesson 10Course 2 week 6 lesson 10
Course 2 week 6 lesson 10
 
MDML@FCPL ILF 2013 Presentation
MDML@FCPL ILF 2013 PresentationMDML@FCPL ILF 2013 Presentation
MDML@FCPL ILF 2013 Presentation
 
Intrnacional tema 2 y 3
Intrnacional tema 2 y 3Intrnacional tema 2 y 3
Intrnacional tema 2 y 3
 
Ubide
UbideUbide
Ubide
 
портфолио Шликова В.В.
портфолио Шликова В.В.портфолио Шликова В.В.
портфолио Шликова В.В.
 
Evoluzione della società umana
Evoluzione della società umana Evoluzione della società umana
Evoluzione della società umana
 
Magazine adverts
Magazine advertsMagazine adverts
Magazine adverts
 
Deeksha ppt
Deeksha pptDeeksha ppt
Deeksha ppt
 
Writing 160 Lesson Pan
Writing 160 Lesson PanWriting 160 Lesson Pan
Writing 160 Lesson Pan
 
John conventions
John conventionsJohn conventions
John conventions
 
Q-Plan
Q-PlanQ-Plan
Q-Plan
 
Java bmi
Java bmiJava bmi
Java bmi
 

Similar to CSP library implements concurrency in Python and Jython

Python Programming Language
Python Programming LanguagePython Programming Language
Python Programming LanguageLaxman Puri
 
CHX PYTHON INTRO
CHX PYTHON INTROCHX PYTHON INTRO
CHX PYTHON INTROKai Liu
 
OpenSAF Symposium_Python Bindings_9.21.11
OpenSAF Symposium_Python Bindings_9.21.11OpenSAF Symposium_Python Bindings_9.21.11
OpenSAF Symposium_Python Bindings_9.21.11OpenSAF Foundation
 
introduction of python in data science
introduction of python in data scienceintroduction of python in data science
introduction of python in data sciencebhavesh lande
 
Researh toolbox-data-analysis-with-python
Researh toolbox-data-analysis-with-pythonResearh toolbox-data-analysis-with-python
Researh toolbox-data-analysis-with-pythonWaternomics
 
Researh toolbox - Data analysis with python
Researh toolbox  - Data analysis with pythonResearh toolbox  - Data analysis with python
Researh toolbox - Data analysis with pythonUmair ul Hassan
 
Introduction to python
Introduction to pythonIntroduction to python
Introduction to pythonMohammed Rafi
 
Python For Audio Signal Processing ( PDFDrive ).pdf
Python For Audio Signal Processing ( PDFDrive ).pdfPython For Audio Signal Processing ( PDFDrive ).pdf
Python For Audio Signal Processing ( PDFDrive ).pdfshaikriyaz89
 
Benchmarking open source deep learning frameworks
Benchmarking open source deep learning frameworksBenchmarking open source deep learning frameworks
Benchmarking open source deep learning frameworksIJECEIAES
 
2015 bioinformatics python_introduction_wim_vancriekinge_vfinal
2015 bioinformatics python_introduction_wim_vancriekinge_vfinal2015 bioinformatics python_introduction_wim_vancriekinge_vfinal
2015 bioinformatics python_introduction_wim_vancriekinge_vfinalProf. Wim Van Criekinge
 
Python standard library &amp; list of important libraries
Python standard library &amp; list of important librariesPython standard library &amp; list of important libraries
Python standard library &amp; list of important librariesgrinu
 

Similar to CSP library implements concurrency in Python and Jython (20)

Python Programming Language
Python Programming LanguagePython Programming Language
Python Programming Language
 
CHX PYTHON INTRO
CHX PYTHON INTROCHX PYTHON INTRO
CHX PYTHON INTRO
 
What is python
What is pythonWhat is python
What is python
 
OpenSAF Symposium_Python Bindings_9.21.11
OpenSAF Symposium_Python Bindings_9.21.11OpenSAF Symposium_Python Bindings_9.21.11
OpenSAF Symposium_Python Bindings_9.21.11
 
introduction of python in data science
introduction of python in data scienceintroduction of python in data science
introduction of python in data science
 
Researh toolbox-data-analysis-with-python
Researh toolbox-data-analysis-with-pythonResearh toolbox-data-analysis-with-python
Researh toolbox-data-analysis-with-python
 
Researh toolbox - Data analysis with python
Researh toolbox  - Data analysis with pythonResearh toolbox  - Data analysis with python
Researh toolbox - Data analysis with python
 
MODULE 1.pptx
MODULE 1.pptxMODULE 1.pptx
MODULE 1.pptx
 
Introduction to python
Introduction to pythonIntroduction to python
Introduction to python
 
Python For Audio Signal Processing ( PDFDrive ).pdf
Python For Audio Signal Processing ( PDFDrive ).pdfPython For Audio Signal Processing ( PDFDrive ).pdf
Python For Audio Signal Processing ( PDFDrive ).pdf
 
Python
PythonPython
Python
 
Python Programming
Python ProgrammingPython Programming
Python Programming
 
Python Course In Chandigarh
Python Course In ChandigarhPython Course In Chandigarh
Python Course In Chandigarh
 
OpenMP
OpenMPOpenMP
OpenMP
 
Python final ppt
Python final pptPython final ppt
Python final ppt
 
Pythonfinalppt 170822121204
Pythonfinalppt 170822121204Pythonfinalppt 170822121204
Pythonfinalppt 170822121204
 
Cmpe202 01 Research
Cmpe202 01 ResearchCmpe202 01 Research
Cmpe202 01 Research
 
Benchmarking open source deep learning frameworks
Benchmarking open source deep learning frameworksBenchmarking open source deep learning frameworks
Benchmarking open source deep learning frameworks
 
2015 bioinformatics python_introduction_wim_vancriekinge_vfinal
2015 bioinformatics python_introduction_wim_vancriekinge_vfinal2015 bioinformatics python_introduction_wim_vancriekinge_vfinal
2015 bioinformatics python_introduction_wim_vancriekinge_vfinal
 
Python standard library &amp; list of important libraries
Python standard library &amp; list of important librariesPython standard library &amp; list of important libraries
Python standard library &amp; list of important libraries
 

More from M H

Map as a Service: A Framework for Visualising and Maximising Information Retu...
Map as a Service: A Framework for Visualising and Maximising Information Retu...Map as a Service: A Framework for Visualising and Maximising Information Retu...
Map as a Service: A Framework for Visualising and Maximising Information Retu...M H
 
Information extraction from sensor networks using the Watershed transform alg...
Information extraction from sensor networks using the Watershed transform alg...Information extraction from sensor networks using the Watershed transform alg...
Information extraction from sensor networks using the Watershed transform alg...M H
 
Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...
Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...
Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...M H
 
An Overview of Information Extraction from Mobile Wireless Sensor Networks
An Overview of Information Extraction from Mobile Wireless Sensor NetworksAn Overview of Information Extraction from Mobile Wireless Sensor Networks
An Overview of Information Extraction from Mobile Wireless Sensor NetworksM H
 
Simulation Issues in Wireless Sensor Networks: A Survey
Simulation Issues in Wireless Sensor Networks: A SurveySimulation Issues in Wireless Sensor Networks: A Survey
Simulation Issues in Wireless Sensor Networks: A SurveyM H
 
Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...
Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...
Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...M H
 
Building Programming Abstractions for Wireless Sensor Networks Using Watershe...
Building Programming Abstractions for Wireless Sensor Networks Using Watershe...Building Programming Abstractions for Wireless Sensor Networks Using Watershe...
Building Programming Abstractions for Wireless Sensor Networks Using Watershe...M H
 
Information Extraction from Wireless Sensor Networks: System and Approaches
Information Extraction from Wireless Sensor Networks: System and ApproachesInformation Extraction from Wireless Sensor Networks: System and Approaches
Information Extraction from Wireless Sensor Networks: System and ApproachesM H
 
An Overview and Classification of Approaches to Information Extraction in Wir...
An Overview and Classification of Approaches to Information Extraction in Wir...An Overview and Classification of Approaches to Information Extraction in Wir...
An Overview and Classification of Approaches to Information Extraction in Wir...M H
 
MuMHR: Multi-path, Multi-hop Hierarchical Routing
MuMHR: Multi-path, Multi-hop Hierarchical RoutingMuMHR: Multi-path, Multi-hop Hierarchical Routing
MuMHR: Multi-path, Multi-hop Hierarchical RoutingM H
 
Experimental Applications of Mapping Services in Wireless Sensor Networks
Experimental Applications of Mapping Services in Wireless Sensor NetworksExperimental Applications of Mapping Services in Wireless Sensor Networks
Experimental Applications of Mapping Services in Wireless Sensor NetworksM H
 
Interpolation Techniques for Building a Continuous Map from Discrete Wireless...
Interpolation Techniques for Building a Continuous Map from Discrete Wireless...Interpolation Techniques for Building a Continuous Map from Discrete Wireless...
Interpolation Techniques for Building a Continuous Map from Discrete Wireless...M H
 
An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...
An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...
An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...M H
 
Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...
Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...
Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...M H
 
Pennies from Heaven: a retrospective on the use of wireless sensor networks f...
Pennies from Heaven: a retrospective on the use of wireless sensor networks f...Pennies from Heaven: a retrospective on the use of wireless sensor networks f...
Pennies from Heaven: a retrospective on the use of wireless sensor networks f...M H
 
An Approach to Data Extraction and Visualisation for Wireless Sensor Networks
An Approach to Data Extraction and Visualisation for Wireless Sensor NetworksAn Approach to Data Extraction and Visualisation for Wireless Sensor Networks
An Approach to Data Extraction and Visualisation for Wireless Sensor NetworksM H
 
Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...
Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...
Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...M H
 

More from M H (17)

Map as a Service: A Framework for Visualising and Maximising Information Retu...
Map as a Service: A Framework for Visualising and Maximising Information Retu...Map as a Service: A Framework for Visualising and Maximising Information Retu...
Map as a Service: A Framework for Visualising and Maximising Information Retu...
 
Information extraction from sensor networks using the Watershed transform alg...
Information extraction from sensor networks using the Watershed transform alg...Information extraction from sensor networks using the Watershed transform alg...
Information extraction from sensor networks using the Watershed transform alg...
 
Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...
Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...
Adaptive Routing in Wireless Sensor Networks: QoS Optimisation for Enhanced A...
 
An Overview of Information Extraction from Mobile Wireless Sensor Networks
An Overview of Information Extraction from Mobile Wireless Sensor NetworksAn Overview of Information Extraction from Mobile Wireless Sensor Networks
An Overview of Information Extraction from Mobile Wireless Sensor Networks
 
Simulation Issues in Wireless Sensor Networks: A Survey
Simulation Issues in Wireless Sensor Networks: A SurveySimulation Issues in Wireless Sensor Networks: A Survey
Simulation Issues in Wireless Sensor Networks: A Survey
 
Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...
Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...
Algorithmic Construction of Optimal and Load Balanced Clusters in Wireless Se...
 
Building Programming Abstractions for Wireless Sensor Networks Using Watershe...
Building Programming Abstractions for Wireless Sensor Networks Using Watershe...Building Programming Abstractions for Wireless Sensor Networks Using Watershe...
Building Programming Abstractions for Wireless Sensor Networks Using Watershe...
 
Information Extraction from Wireless Sensor Networks: System and Approaches
Information Extraction from Wireless Sensor Networks: System and ApproachesInformation Extraction from Wireless Sensor Networks: System and Approaches
Information Extraction from Wireless Sensor Networks: System and Approaches
 
An Overview and Classification of Approaches to Information Extraction in Wir...
An Overview and Classification of Approaches to Information Extraction in Wir...An Overview and Classification of Approaches to Information Extraction in Wir...
An Overview and Classification of Approaches to Information Extraction in Wir...
 
MuMHR: Multi-path, Multi-hop Hierarchical Routing
MuMHR: Multi-path, Multi-hop Hierarchical RoutingMuMHR: Multi-path, Multi-hop Hierarchical Routing
MuMHR: Multi-path, Multi-hop Hierarchical Routing
 
Experimental Applications of Mapping Services in Wireless Sensor Networks
Experimental Applications of Mapping Services in Wireless Sensor NetworksExperimental Applications of Mapping Services in Wireless Sensor Networks
Experimental Applications of Mapping Services in Wireless Sensor Networks
 
Interpolation Techniques for Building a Continuous Map from Discrete Wireless...
Interpolation Techniques for Building a Continuous Map from Discrete Wireless...Interpolation Techniques for Building a Continuous Map from Discrete Wireless...
Interpolation Techniques for Building a Continuous Map from Discrete Wireless...
 
An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...
An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...
An Integrated Inductive-Deductive Framework for Data Mapping in Wireless Sens...
 
Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...
Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...
Modelling Clustering of Wireless Sensor Networks with Synchronised Hyperedge ...
 
Pennies from Heaven: a retrospective on the use of wireless sensor networks f...
Pennies from Heaven: a retrospective on the use of wireless sensor networks f...Pennies from Heaven: a retrospective on the use of wireless sensor networks f...
Pennies from Heaven: a retrospective on the use of wireless sensor networks f...
 
An Approach to Data Extraction and Visualisation for Wireless Sensor Networks
An Approach to Data Extraction and Visualisation for Wireless Sensor NetworksAn Approach to Data Extraction and Visualisation for Wireless Sensor Networks
An Approach to Data Extraction and Visualisation for Wireless Sensor Networks
 
Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...
Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...
Enhancing Student Learning Experience and Satisfaction Using Virtual Learning...
 

Recently uploaded

Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Kaya Weers
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 

Recently uploaded (20)

Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)Design pattern talk by Kaya Weers - 2024 (v2)
Design pattern talk by Kaya Weers - 2024 (v2)
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 

CSP library implements concurrency in Python and Jython

  • 1. Communicating Process Architectures 2009 1 Peter Welch, Herman Roebbers and Tobe Announced (Eds.) IOS Press, 2009 c 2009 The authors and IOS Press. All rights reserved. CSP as a Domain-Specific Language Embedded in Python and Jython Sarah Mount 1 , Mohammad Hammoudeh, Sam Wilson and Robert Newman School of Computing and I.T., University of Wolverhampton, U.K. Abstract. Recently, much discussion has taken place within the Python programming community on how best to support concurrent programming. This paper describes a new Python library, python-csp, which implements synchronous, message-passing concurrency based on Hoare’s Communicating Sequential Processes. Although other CSP libraries have been written for Python, python-csp has a number of novel fea- tures. The library is implemented both as an object hierarchy and as a domain-specific language, meaning that programmers can compose processes and guards using infix operators, similar to the original CSP syntax. The language design is intended to be idiomatic Python and is therefore quite different to other CSP libraries. python-csp targets the CPython interpreter and has variants which reify CSP process as Python threads and operating system processes. An equivalent library targets the Jython in- terpreter, where CSP processes are reified as Java threads. jython-csp also has Java wrappers which allow the library to be used from pure Java programs. We describe these aspects of python-csp, together with performance benchmarks and a formal analysis of channel synchronisation and choice, using the model checker SPIN. Keywords. Communicating Sequential Processes, Python, Dynamic Languages, Domain-Specific Languages Introduction Python is a lexically scoped, dynamically typed language with object-oriented features, whose popularity is often said to be due to its ease of use. The rise of multi-core processor architectures and web applications has turned attention in the Python community to concur- rency and distributed computing. Recent versions of Python have language-level or standard library support for coroutines2 , (system) threads3 and process4 management, the latter two largely in the style of the POSIX thread library. This proliferation of concurrency styles is somewhat in contrast to the “Zen” of Python [?] which states that “There should be one—and preferably only one—obvious way to do it.”. One reason for adding coroutines (and therefore the ability to use “green” threads) and operating-system processes is the performance penalty of using Python threads, which is largely due to the presence of the global interpreter lock (GIL) in the C implementation of the Python interpreter. The GIL is implemented as an operating system semaphore or condition variable which is acquired and released in the interpreter every time the running thread blocks 1 Corresponding Author: Sarah Mount, School of Computing and I.T., University of Wolverhampton, Wulfruna St., Wolverhampton, WV1 1SB, U.K.. Tel.: +44 1902 321832; Fax: +44 1902 321478; E-mail: s.mount@wlv.ac.uk. 2 Python PEP 342: Coroutines via Enhanced Generators http://www.python.org/dev/peps/pep-0342/ 3 http://docs.python.org/library/threading.html#module-threading 4 http://docs.python.org/library/multiprocessing.html#module-multiprocessing
  • 2. 2 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython for I/O, allowing the operating system to schedule a different thread. A recent presentation by Dave Beazley5 contained benchmarks of the following CPU-bound task: 1 def count ( n ): 2 while n > 0: 3 n -= 1 and found that a parallel execution of the task in threads performed 1.8 times slower than a sequential execution and that performance improved if one (of two) CPU cores was disabled. These counter-intuitive results are often the basis for developers to call for the GIL to be removed. The Python FAQ6 summarises why the GIL is unlikely to be removed from the reference implementation of the interpreter, essentially because alternative implementations of thread scheduling have caused a performance penalty to single-threaded programs. The current solution, therefore, is to provide programmers with alternatives: either to write single- threaded code, perhaps using coroutines for cooperative multitasking, or to take advantage of multiple cores and use processes and IPC in favour of threads and shared state. A second solution is to use another implementation of Python, apart from the CPython interpreter. Stackless Python [?] is an implementation which largely avoids the use of the C stack and has green threads (called “tasklets”) as part of its standard library. Google’s Unladen Swallow7 is still in the design phase, but aims to improve on the performance of CPython five-fold and intends to eliminate the GIL in its own implementation by 2010. This paper describes another alternative, to augment Python with a higher-level abstrac- tion for message-passing concurrency, python-csp based on Hoare’s Communicating Se- quential Processes [?]. The semantics of CSP are relatively abstract compared with libraries such as pthreads and so the underlying implementation of CSP “processes” as either sys- tem threads, processes or coroutines is hidden from the user. This means that the user can choose an implementation which is suitable for the interpreter in use or the context of the application they are developing (for example, processes where a multi-core architecture is expected to be used, threads where one is not). Also CSP was designed specifically to help avoid well-known problems with models such as shared memory concurrency (such as dead- locks and race conditions) and to admit formal reasoning. Both properties assist the user by encouraging program correctness. The authors have a particular interest in using Python to implement complex tasks requiring coordination between many hosts. The SenSor simulator and development tool [?,?] provided facilities for prototyping algorithms and applications for wireless sensor networks in pure Python, using shared-memory concurrency. The burden of managing explicit locking in an already complex environment made the implementation of SenSor difficult. A new version of the tool is currently under development and will be built on the python-csp and jython-csp libraries. To deal with the different performance characteristics of threads and processes in the cur- rent implementations of Python, the python-csp library currently has a number of different implementations: • The csp.cspprocess module which contains an implementation of python-csp based on operating system processes, as managed by the multiprocessing library; and • the csp.cspthread module which contains an implementation of python-csp based on system threads. There is also a version of the library called jython-csp that targets Jython, a version of Python which runs on the Java VM. jython-csp uses Java threads (which are also sys- 5 http://blip.tv/file/2232410 6 http://www.python.org/doc/faq/library/ 7 http://code.google.com/p/unladenswallow/
  • 3. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 3 tem threads), rather than Python threads. Jython allows the user to mix Java and Python code in programs (almost) freely. As such, jython-csp allows users to use any combina- tion of Python and Java, including being able to write pure Java programs using wrappers for jython-csp types. In general, in this paper we will refer to python-csp, however, the syntax and semantics of the libraries can be assumed to be identical, unless stated otherwise. The remainder of this paper describes the design and implementation of python-csp and jython-csp. Section ?? gives an overview of the design philosophy of the library and its syntax and (informal) semantics. Section ?? describes a longer python-csp program and gives a discussion of the design patterns used in the implementation. Section ?? begins an evaluation of python-csp by describing benchmark results using the Commstime program and comparing our work with similar libraries. python-csp and jython-csp have been bench-marked against PyCSP [?], another realisation of CSP in Python and JCSP [?], a Java library. Section ?? outlines ongoing work on model checking channel synchronisation and non-deterministic selection in the python-csp implementation. Section ?? concludes and describes future work. 1. python-csp and jython-csp: Syntax and Semantics The design philosophy behind python-csp is to keep the syntax of the library as “Pythonic” and familiar to Python programmers as possible. In particular, two things distinguish this li- brary from others such as JCSP [?] and PyCSP [?]. Where languages such as Java have strong typing and sophisticated control over encapsulation, Python has a dynamic type system, often using so-called “duck typing” (which means that an object is said to implement a particular type if it shares enough data and operations with the type to be used in the same context as the type). Where an author of a Java library might expect users to rely on the compiler to warn of semantic errors in the type-checking phase, Python libraries tend to trust the user to manage their own encapsulation and use run-time type checking. Although Python is a dynamically typed language, the language is helpful in that few, if any, type coercions are implicit. For example, where in Java, a programmer could concatenate a String and an int type when calling System.out.println, the equivalent expression in Python would raise an exception. In general, the Python type system is consistent and this is largely because every Python type is reified as an object. Java differs from Python in this respect, as primitive Java types (byte, short, int, long, char, float, double, boolean) do not have fields and are not created on the heap. In Python, however, all values are (first-class) objects, including functions and classes. Importantly for the work described here, operators may be overloaded for new types as each Python operator has an equivalent method inherited from the base object, for example: 1 >>> 1 + 2 2 3 3 >>> (1). __add__ (2) 4 3 5 >>> [1] * 3 6 [1 , 1 , 1] 7 >>> ([1]). __mul__ (3) 8 [1 , 1 , 1] 9 >>>
  • 4. 4 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython Lastly, Python comes with a number of features familiar to users of functional programming languages such as ML that are becoming common in modern, dynamically typed languages. These include generators, list comprehensions and higher-order functions. CSP [?] contains three fundamental concepts: processes, (synchronous) channel com- munication and non-deterministic choice. python-csp provides two ways in which the user may create and use these CSP object types: one method where the user explicitly creates instances of types defined in the library and calls the methods of those types to make use of them; and another where users may use syntactic sugar implemented by overriding the Python built in infix operators. Operator overloading has been designed to be as close to the original CSP syntax as possible and is as follows: Syntax Meaning CSP equivalent P>Q Sequential composition of processes P; Q P&Q Parallel composition of processes P Q c1 | c2 Non-deterministic choice c1 c2 n∗A Repetition n•A A∗n Repetition n•A Skip() Skip guard, always ready to synchronise Skip where: • n is an integer; • P and Q are processes; • A is a non-deterministic choice (or ALT); and • c1 and c2 are channels. The following sections describe each of the python-csp features in turn. 1.1. python-csp processes In python-csp a process can be created in two ways: either explicitly by creating an instance of the CSPProcess class or, more commonly, by using the @process decorator8 . In either case, a callable object (usually a function) must be created that describes the run-time behaviour of the process. Listing ?? shows the two ways to create a new process, in this case one which opens a sensor connected to the USB bus of the host and continuously prints out a transducer reading every five minutes. Whichever method is used to create the process, P, a special keyword argument _process must be passed in with a default value. When the process P is started (by calling its start method) _process is dynamically bound to an object representing the underlying system thread or process which is the reification of the CSPProcess instance. This gives the programmer access to values such as the process identifier (PID), or thread name which may be useful for logging and debugging purposes. When the start methods in 8 A “decorator” in Python is a callable object “wrapped” around another callable. For example, the definition of a function fun decorated with the @mydec decorator will be replaced with fun = mydec(fun).
  • 5. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 5 a CSPProcess object has returned the underlying thread or process will have terminated. Once this has happened, accessing the methods or data of the corresponding _process variable will raise an exception. 1 # Using the CSPProcess class : 2 def print_rh_reading (): 3 rhsensor = ToradexRH () # Oak temp / humidity sensor 4 rhsensor . open () 5 while True : 6 data = rhsensor . get_data () 7 print ’ Humidity %% g : Temp : % gC ’ % data [1:] 8 dingo . platform . gumstix . sleep (60 * 5) # 5 min 9 P = CSPProcess ( print_rh_reading , _process = None ) 10 P . start () 11 12 # Using the @process decorator : 13 @process 14 def print_rh_reading ( _process = None ): 15 rhsensor = ToradexRH () # Oak temp / humidity sensor 16 rhsensor . open () 17 while True : 18 data = rhsensor . get_data () 19 print ’ Humidity %% g : Temp : % gC ’ % data [1:] 20 dingo . platform . gumstix . sleep (60 * 5) # 5 min 21 P = print_rh_reading () 22 P . start () Listing 1: Two ways to create a python-csp process. 1.2. python-csp parallel and sequential execution CSP processes can be composed either sequentially or in parallel. In sequential execution each process starts and terminates before the next in the sequence begins. In parallel execu- tion all processes run “at once” and therefore the order of any output they effect cannot be guaranteed. Parallel and sequential execution can be implemented in python-csp either by instantiating Par and Seq objects or by using the overloaded & or > operators. In general, using the overloaded infix operators results in clear, simple code where there are a small number of processes. Listing ?? demonstrates sequential and parallel process execution in python-csp. 1 ... def P (n , _process = None ): 2 ... print n 3 ... 4 >>> # In sequence , using syntactic sugar ... 5 >>> P (1) > P (2)
  • 6. 6 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 6 1 7 2 8 >>> # In sequence , using objects ... 9 >>> Seq ( P (1) , P (2)). start () 10 1 11 2 12 >>> # In parallel , using syntactic sugar ... 13 >>> P (1) & P (2) 14 2 15 1 16 >>> # In parallel , using objects ... 17 >>> Par ( P (1) , P (2)). start () 18 1 19 2 Listing 2: Two ways to run processes sequentially and in parallel. 1.3. python-csp channels In CSP communication between processes is achieved via channels. A channel can be thought of as a pipe (similar to UNIX pipes) between processes. One process writes data down the channel and the other reads. Since channel communication in CSP is synchronous, the writing channel can be thought of as offering data which is only actually written to the channel when another process is ready to read it. This synchronisation is handled entirely by the language, meaning that details such as locking are invisible to the user. Listing ?? shows how channels can be used in python-csp. In its csp.cspprocess implementation, python-csp uses an operating system pipe to transmit serialised data between processes. This has a resource constraint, as operating sys- tems limit the number of file descriptors that each process may have open. This means that although python-csp programs can create any number of processes (until available memory is saturated), a limited number of channels can be created. In practice this is over 600 on a Ubuntu Linux PC. To compensate for this, python-csp offers a second implementation of channels called FileChannel. A FileChannel object behaves in exactly the same way as any other channel, except that it uses files on disk to store data being transferred between pro- cesses. Each read or write operation on a FileChannel opens and closes the operating system file, meaning that the file is not open for the duration of the application running time. Pro- grammers can use FileChannel objects directly, or, if a new Channel object cannot be instan- tiated then Channel will instead return a FileChannel object. A third class of channel is provided by python-csp, called a NetworkChannel. A NetworkChannel transfers data between processes via a socket listener which resides on each node in the network for the purpose of distributing channel data. By default when the Python csp.cspprocess package is imported, a socket server is started on the host (if one is not al- ready running). 1 @process 2 def send_rh_reading ( cout , _process = None ):
  • 7. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 7 3 rhsensor = ToradexRH () # Oak temp / humidity sensor 4 timer = TimerGuard () 5 rhsensor . open () 6 while True : 7 data = rhsensor . get_data () 8 cout . send ( ’ Humidity %% g : Temp : % gC ’ % data [1:]) 9 timer . sleep (60 * 5) # 5 min 10 guard . read () # Synchronise with timer guard . 11 12 @process 13 def simple_sensor ( _process = None ): 14 ch = Channel () 15 Printer ( ch ) & send_rh_reading ( ch ) Listing 3: Two processes communicating via a channel. 1.4. Non-deterministic selection and guards in python-csp Non-deterministic selection (called “select” in JCSP and “ALT” or “ALTing” in occam) is an important feature of many process algebras. Select allows a process to choose between a number of waiting channel reads, timers or other “guards” which are ready to synchronise. In python-csp this is achieved via the select method of any guard type. To use select an Alt object must be created and should be passed any number of Guard instances. See Listing ?? for an example. The select method can be called on the Alt object and will return the value returned from the selected guard. To implement a new guard type, users need to subclass the Guard class and provide the following methods: enable which should attempt to synchronise. disable which should roll back from an enable call to the previous state. is selectable which should return True if the guard is able to complete a synchronous transaction and False otherwise. select which should complete the synchronous transaction and return the result (note this semantics is slightly different from that found in JCSP, as described by Welch [?], where an index to the selected guard in the guard array is returned by select). poison which should be used to finalize and delete the current guard and gracefully termi- nate any processes connected with it [?,?]. Since Python has little support for encapsulation, the list of guards inside an Alt object is available to any code which has access to the Alt. 1 @process 2 def p r i n t A v a i l a b l e R e a d i n g ( cins , _process = None ): 3 alt = Alt ( cins ) 4 while True : 5 print alt . select () 6 @process
  • 8. 8 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 7 def s impleS ensorA rray ( _process = None ): 8 chans , procs = [] , [] 9 for i in NUMSENSORS : 10 chans . append ( Channel ()) 11 procs . append ( sendRHReading ( chans [ -1])) 12 procs . append ( p r i n t A v a i l a b l e R e a d i n g ( chans )) 13 Par (* procs ). start () Listing 4: Servicing the next available sensor reading with non-deterministic selection. Like many other implementations of CSP, python-csp implements a number of variants of non-deterministic selection: select enables all guards and either returns the result of calling select on the first available guard (if only one becomes available) or randomly chooses an available guard and returns the result of its select method. The choice is truly random and determined by a random number generator seeded by the urandom device of the host machine. priority select enables all guards and, if only one guard becomes available then priority_select returns the result of its select method. If more than one guard be- comes available the first guard in the list passed to Alt is selected. fair select enables all guards and, if only one guard becomes available then fair_select returns the result of its select method. Alt objects keep a reference to the guard which was selected on the previous invocation of any select method, if there has been such an invocation and the guard is still in the guards list. If fair_select is called and more than one guard becomes available, then fair_select gives lowest priority to the guard which was returned on the previous invocation of any of the select methods. This idiom is used to reduce the likelihood of starvation as every guard is guaranteed that no other guard will be serviced twice before it is selected. There are two forms of syntactic sugar that python-csp implements to assist in dealing with Alt objects: a choice operator and a repetition operator. Using the choice operator, users may write: 1 result = guard_1 | guard_2 | ... | guard_n which is equivalent to: 1 alt = Alt ( guard_1 , guard_2 , ... , guard_n ) 2 result = alt . select () To repeatedly select from an Alt object n times, users may write: 1 gen = n * Alt ( guard_1 , guard_2 , ... , guard_n ) or: 1 gen = Alt ( guard_1 , guard_2 , ... , guard_n ) * n this construct returns a generator object which can be iterated over to obtain results from Alt.select method calls. Using generators in this way is idiomatic in Python and will be familiar to users. The following is a typical use case:
  • 9. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 9 1 gen = Alt ( guard_1 , guard_2 , ... , guard_n ) * n 2 while True : 3 ... gen . next () ... Each time gen.next() is called within the loop, the select() method of the Alt object is called, and its result returned. In addition to channel types, python-csp implements two commonly used guard types: Skip and TimerGuards. Skip is the guard which is always ready to synchronise. In python-csp its select method always returns None, which is the Python null value. TimerGuards are used to either suspend a running process (by calling their sleep method) or as part of a synchroni- sation where the guard will become selectable after a timer has expired: 1 @process 2 def alarm ( self , cout , _process = None ): 3 alt = Alt ( TimerGuard ()) 4 t0 = alt . guard [0]. read () # Fetch current time 5 alt . guard [0]. set_alarm (5) # Selectable 5 secs from now 6 alt . select () 7 duration = guard . read () - t0 # In seconds 8 cout . write ( duration ) 1.5. Graceful process termination in python-csp Terminating a parallel program without leaving processes running in deadlock is a difficult problem. The most widely implemented solution to this problem was invented by Peter Welch [?] and is known as “channel poisoning”. The basic idea is to send a special value down a channel which, when read by a process, is then propagated down any other channels known to that process before it terminates. In python-csp this can be affected by calling the poison method on any guard. A common idiom in python-csp, especially where producer / consumer patterns are implemented, is this: 1 alt = Alt (* channels ) 2 for i in xrange ( len ( channels )): 3 alt . select () Here, it is intended that each guard in channels be selected exactly once. Once a guard has been selected its associated writer process(es) will have finished its computation and ter- minate. In order to support this idiom efficiently, python-csp implements a method called poison on Alt objects which serves to poison the writer process(es) attached to the last se- lected guard and remove that guard from the list, used as follows: 1 a = Alt (* channels ) 2 for i in xrange ( len ( channels )): 3 a . select () 4 a . poison ()
  • 10. 10 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython By shortening the list of guards less synchronisation is required on each iteration of the for loop, reducing the computational effort required by the select method. 1.6. Built-in processes and channels python-csp comes with a number of built-in processes and channels, aimed to speed de- velopment. This includes all of the names defined in the JCSP “plugnplay” library. In addi- tion to these and other built-in processes and guards, python-csp comes with analogues of every unary and binary operator in Python. For example, the Plus process reads two values from channels and then writes the addition of those values to an output channel. An example implementation9 of this might be: 1 @process 2 def Plus ( cin1 , cin2 , cout , _process = None ): 3 while True : 4 in1 = cin1 . read () 5 in2 = cin2 . read () 6 cout . write ( in1 + in2 ) 7 return Listing 5: A simple definition of the built-in Plus process. 1.7. jython-csp implementation and integration with pure Java jython-csp is a development of python-csp for integration with Jython. Jython has sim- ilar semantics as Python but uses the Java runtime environment (JRE) which allows access to the large number of Java libraries, such as Swing, which are useful, platform-independent and well optimised. jython-csp has similar workings to the initial python-csp with the ability to utilise any class from the standard Java and Python class libraries. jython-csp utilises Java threads and would be expected to perform similarly to other CSP implementa- tions based on Java threads, such as JCSP (e.g. [?]). A comparison between jython-csp and python-csp implementations of the Monte Carlo approximation to π is shown in Table ??. Table 1. Results of testing Java threads against Python threads and OS processes. Thread Library Running time of π approximation (seconds) jython-csp (Java Threads) 26.49 python-csp (Python Threads) 12.08 python-csp (OS Processes) 9.59 As we shall see in Section ?? the JCSP library performs channel communication very efficiently, so one might expect that jython-csp would also execute quickly. A speculation as to why jython-csp (using Java threads) performs poorly compared to the other CSP implementations is a slow Java method dispatch within Jython. 9 In fact, these processes are implemented slightly differently, taking advantage of Python’s support for re- flection. Generic functions called _applybinop and _applyunaryop are implemented, then Plus may be de- fined simply as Plus = _applybinop(operator.__add__). The production version of this code is slightly more complex as it allows for documentation for each process to be provided whenever _applybinop and _applyunaryop are called.
  • 11. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 11 In addition to the modification of the threading library used jython-csp also takes ad- vantage of Java locks and semaphores from the java.util.concurrent package. jython-csp has no dependency on non standard packages; the library will work with any JRE which is compatible with Jython 2.5.0final. 1.8. Java-csp Java-csp is the integration of jython-csp with Java to allow Java applications to utilise the flexibility of jython-csp. The Java CSP implementation attempts to emulate the built in Java thread library (java.lang.Thread) with a familiar API. As with Java threads there are two ways to use threads in an application: • By extending the Thread class and overwriting the run method; or • By implementing the Runnable interface. The Java csp implementation has a similar usage: • Extending the JavaCspProcess and overwriting the target method; or • Implementing the JavaCspProcessInterface interface. jython-csp and python-csp uses the pickle library as a means of serialising data down a channel. Pickle takes a Python/Jython object and returns a sequence of bytes; this approach only works on Python/Jython object and is unsuitable for native Java objects. As a solution java-csp implements a wrapped version of Java object serialization which allows Jython to write pure Java objects, which implement the Serializable interface, to a channel, in addition to this, Python/Jython objects can be written down a channel if they extend the PyObject class. 2. Mandelbrot generator: an example python-csp program 2.1. Mandelbrot generator Listing ?? shows a longer example of a python-csp program as an illustration of typical cod- ing style. The program generates an image of a Mandelbrot set which is displayed on screen using the PyGame library10 (typically used for implementing simple, 2D arcade games). The Mandelbrot set is an interesting example, since it is embarrassingly parallel – i.e. each pixel of the set can be calculated independently of the others. However, calculating each pixel of a large image in a separate process may be a false economy. Since channel communication is likely to be an expensive part, the resulting code is likely to be I/O bound. The code in Listing ?? is structured in such a way that each column in the image is generated by a separate “producer” process. Columns are stored in memory as a list of RGB tuples which are then written to a channel shared by the individual producer process and a single “consumer” process. The main work of the consumer is to read each image column via an Alt object and write it to the display surface. This producer / consumer architecture is common to many parallel and distributed pro- grams. It it not necessarily, however, the most efficient structure for this program. Since some areas of the set are essentially flat and so simple to generate, many producer processes are likely to finish their computations early and spend much of their time waiting to be selected by the consumer. If this is the case, it may be better to use a “farmer” process to task a smaller number of “worker” processes with generating a small portion of the image, and then re-task each worker after it has communicated its results to the farmer. Practically, if efficiency is 10 http://www.pygame.org
  • 12. 12 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython an important concern, these options need to be prototyped and carefully profiled in order to determine the most appropriate solution to a given problem. 1 from csp . cspprocess import * 2 @process 3 def mandelbrot ( xcoord , ( width , height ) , cout , 4 acorn = -2.0 , bcorn = -1.250 , _process = None ): 5 # Generate image data for column xcoord ... 6 cout . write (( xcoord , imgcolumn )) 7 _process . _terminate () 8 @process 9 def consume ( IMSIZE , filename , cins , _process = None ): 10 # Create initial pixel data . 11 pixmap = Numeric . zeros (( IMSIZE [0] , IMSIZE [1] , 3)) 12 pygame . init () 13 screen = pygame . display . set_mode (( IMSIZE [0] , IMSIZE [1]) , 0) 14 # Wait on channel data . 15 alt = ALT (* cins ) 16 for i in range ( len ( cins )): 17 xcoord , column = alt . select () 18 alt . poison () # Remove last selected guard and producer . 19 # Update column of blit buffer 20 pixmap [ xcoord ] = column 21 # Update image on screen . 22 pygame . surfarray . blit_array ( screen , pixmap ) 23 def main ( IMSIZE , filename ): 24 channels , processes = [] , [] 25 for x in range ( IMSIZE [0]): # Producer + channel per column . 26 channels . append ( Channel ()) 27 processes . append ( mandelbrot (x , IMSIZE , channels [ x ])) 28 processes . insert (0 , consume ( IMSIZE , filename , channels )) 29 mandel = PAR (* processes ) 30 mandel . start () Listing 6: Mandelbrot set in python-csp (abridged). The worker/ farmer architecture shows an improvement in performance over the pro- ducer / consumer architecture. The code in Listing ?? is structured in such a way that each column in the image is computed by a single process. Initially a set of workers are created and seeded with the value of the column number, the pixel data for that column is generated then written to a channel. When the data has been read, the “farmer” then assigns a new col- umn for the worker to compute, if there are no remaining columns to be generated the farmer will write a terminating value and the worker will terminate, this is required to instruct the
  • 13. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 13 “worker” that there are no more tasks to be performed. The consumer has the same function as before although with a smaller set of channels to choose from. Workers which have com- pleted their assigned values have a shorter amount of time to wait until the Alt object selects them. 1 @process 2 def mandelbrot ( xcoord , ( width , height ) , cout , 3 acorn = -2.0 , bcorn = -1.250 , _process = None ): 4 # Generate image data for column xcoord ... 5 cout . write (( xcoord , imgcolumn )) 6 xcoord = cout . read () 7 if xcoord == -1: 8 _process . _terminate () 9 @process 10 def consume ( IMSIZE , filename , cins , _process = None ): 11 global SOFAR 12 # Create initial pixel data 13 pixmap = Numeric . zeros (( IMSIZE [0] , IMSIZE [1] , 3)) 14 pygame . init () 15 screen = pygame . display . set_mode (( IMSIZE [0] , IMSIZE [1]) , 0) 16 # Wait on channel data 17 alt = Alt (* cins ) 18 for i in range ( IMSIZE [0]): 19 xcoord , column = alt . pri_select () 20 # Update column of blit buffer 21 pixmap [ xcoord ] = column 22 # Update image on screen . 23 pygame . surfarray . blit_array ( screen , pixmap ) 24 if SOFAR < IMSIZE [0]: 25 alt . last_selected . write ( SOFAR ) 26 SOFAR = SOFAR + 1 27 else : 28 alt . last_selected . write ( -1) Listing 7: Mandelbrot set in python-csp (abridged) using the “farmer” /“worker” architec- ture. The improvement in performance can been seen in Figure ??, using a smaller number of processes reduces the run time of the program. The graph shows a linear characteristic, which would be expected as the select method in Alt is O(n).
  • 14. 14 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython Figure 1. Run times of “farmer” / “worker” Mandelbrot program with different numbers of CSP processes. 3. Performance evaluation and comparison to related work The Commstime benchmark was originally implemented in occam by Peter Welch at the University of Kent at Canterbury and has since become the de facto benchmark for CSP implementations such as occam-π [?], JCSP [?] and PyCSP [?]. Table ?? shows results of running the Commstime benchmark on JCSP version 1.1rc4, PyCSP version 0.6.0 and python-csp. To obtain fair results the implementation of Comm- stime used in this study was taken directly from the PyCSP distribution, with only syntactic changes made to ensure that tests run correctly and are fairly comparable. In each case, the type of “process” used has been varied and the default channel implementation has been used. In the case of the python-csp channels are reified as UNIX pipes. The JCSP implementation uses the One2OneChannelInt class. The PyCSP version uses the default PyCSP Channel class for each process type. All tests were run on an Intel Pentium dual-core 1.73GHz CPU and 1GB RAM, running Ubuntu 9.04 (Jaunty Jackalope) with Linux kernel 2.6.28-11-generic. Version 2.6.2 of the CPython interpreter was used along with Sun Java(TM) SE Runtime Environment (build 1.6.0 13-b03) and Jython 2.50. Table 2. Results of testing various CSP libraries against the Commstime benchmark. In each case the default Channel class is used. CSP Process min max mean standard implementation reification (µ s) (µ s) (µ s) deviation JCSP JVM thread 15 29 23.8 4.29 PyCSP OS process 195.25 394.97 330.34 75.82 PyCSP Python thread 158.46 311.2 292.2 47.21 PyCSP Greenlet 24.14 25.37 24.41 0.36 python-csp OS process 67.6 155.97 116.75 35.53 python-csp Python thread 203.05 253.56 225.77 17.51 jython-csp JVM thread 135.05 233 157.8 30.78 The results show that channel operations in jython-csp are faster than channel opera- tions between python-csp objects when reified as threads, but slower than the thread-based version of python-csp. This is a surprising result, as Java threads are better optimised than Python threads (because of the way the Python GIL is implemented) and, as the results for JCSP show, it is possible to implement CSP channels very efficiently in pure Java. The loss of performance is likely to be due to the way in which methods are invoked in Jython. Rather
  • 15. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 15 than all compiling Jython code directly to Java bytecode (as was possible when Jython sup- ported the jythonc tool), Jython wraps Python objects in Java at compile time and executes pure Python code in and instance of a Python interpreter. Mixing Python and Java code, as the jython-csp library does, can therefore result in poor performance. It may be possible to ameliorate these problems by implemented more of the jython-csp library in pure Java code. It is also possible that future versions of Jython will improve the performance of method invocation and/or provide a method of compiling Python code directly to Java bytecode. The difference between the python-csp and PyCSP libraries is also surprising. python-csp implements channel synchronisation in a simple manner, with two semaphores protecting each channel, and two reentrant locks to guard against conflicts between multiple readers and/or writers. PyCSP has a very different architecture and synchronisation strategy which may account for the difference in performance. More detailed profiling of the two libraries, together with the completion of the model checking work described in Section (to ensure that python-csp is not simply faster because it is somehow incorrect) will form part of our future work. 3.1. Related work There are some differences between the implementation of python-csp and other realisa- tions of CSP, such as occam-π, JCSP [?] and PyCSP [?]. In particular, any channel object may have multiple readers and writers. There are no separate channel types such as JCSPs One2OneChannel. This reflects the simplicity that Python programmers are used to and the PEP20 [?] maxim that ““There should be one—and preferably only one—obvious way to do it.”. Also, when a Channel object (or variant of such) is instantiated, the instance itself is returned to the caller. In contrast, other systems return a “reader” and “writer” object, often implemented as the read and write method of the underlying channel. This is similar to the implementation of operating system pipes in many libraries, where a reader and writer to the pipe is returned by a library call, rather than an abstraction of the pipe. The authors of these other CSP realisations would argue that their design is less likely to be error prone and that they are protecting the error-prone programmer from inadvertently reading from a channel that is intended to be a “output” channel to the given process or writing to a channel that is intended to be an “input” to the process. However, python-csp comes with strong tool sup- port which may ameliorate some of these potential errors, and the profusion of channel types in some systems may confuse rather than simplify. Similarly, Alt.select methods return the value read by a guard rather than the index to the selected guard (as in JCSP) or a reference to the selected guard (PyCSP). The last guard selected is stored in the field Alt.last_selected and so is available to users. Some pragmatic concessions to the purity of python-csp have been made. In particular, the three default channel types (Channel, FileChannel and NetworkChannel) have very different performance and failure characteristics and so are implemented separately and conspicuously to the user. The chances of a network socket failing, and the potential causes of such a fail- ure, differ greatly from that of an operating system pipe. Equally, a process which times-out waiting for a channel read will need to wait considerably longer for a read on a FileChannel than a Channel. These are non-trivial differences in semantics and it seems beneficial to make them explicit. 4. Correctness of synchronisation in python-csp 4.1. SPIN To verify the correctness of synchronisation in python-csp, a formal model was built using high level language to specify systems descriptions, called Promela (a PROcess MEta LAn-
  • 16. 16 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython guage). This choice is motivated by convenience since a large number of Promela models are available in the public domain and some of the features of the SPIN (Simple Promela INter- preter) tool environment [?], which interprets Promela, greatly facilitate our model analysis. Given a model system specified in Promela, SPIN can generate a c program that performs a fast exhaustive verification of the system state space. In addition, SPIN can perform random or guided simulations of the system’s execution following one possible execution path through the system and showing the resulting execution trace to the user. During simulations and ver- ifications SPIN checks for the presence of deadlocks, livelocks, starvation, race conditions, unspecified receptions, and unexecutable code. As a simulator, SPIN allows for rapid proto- typing of systems by visualising communications between different entities/processes. The verifier can be used to prove the correctness of system invariants and to reveal serious design problems in the model. Finally, SPIN supports the verification of linear time temporal con- straints; either with Promela never-claims/assertions or by directly formulating the constraints in temporal logic. 4.2. Promela Promela is a non-deterministic language, loosely based on Dijkstra’s guarded command lan- guage notation and borrowing the notation for i/o operations from Hoare’s CSP language. Promela provides all of the necessary features to trace logical design errors in distributed con- current algorithms such as parallel and asynchronous composition of concurrent processes, guarded and non-deterministic control structures, communication channels, and sending and receiving primitives. The syntax of Promela is c-like. Promela models consist of processes, message channels, and variables. Processes (proctype) are global objects that represent the concurrent entities of a distributed system. Message channels (chan) and data objects define the environment in which the processes run. Statements are either enabled or blocked. Blocking is a primary mechanism to enforce synchronising communication between processes. The sending or re- ceiving process blocks until the system transfers the message. If a statement is blocked, ex- ecution at that point halts until the statement becomes enabled or control can be transferred outside the scope of the statement by explicit goto. If this statement afterwards becomes en- abled again, execution may continue at that point. The initialisation process init is often used to begin the main of the code to model the global system process. It prepares the ini- tial state of the system by initialising global variables and instantiating the appropriate pro- cesses. It should be employed to activate simultaneously (run) process-instances of agents and potentially the environment. 4.3. Model checking results The model was divided into the three primary processes: the ALT, the read, and the write. Syn- chronisation was modelled by semaphores for several readers and several writers in Promela. Process type declarations consist of the keyword proctype, followed by the name of the pro- cess type, and an argument list. For example, N instances of the process type read are defined as follows: 1 active [ N ] proctype reader () 2 { ( rlock ) -> rlock = false ; 3 read (); 4 rlock = true ; 5 skip } 6
  • 17. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 17 7 inline read () 8 { lock ( listlock ); 9 if 10 :: is_selectable [0] && waiting [0] -> 11 do 12 :: ( rlock ) -> rlock = false ; /* obtain rlock */ 13 atomic { /* wait ( sem ) acquire available */ 14 available > 0 -> available - -;} 15 c_r ? msg ; /* get data from pipe critical section */ 16 taken ++; /* release taken */ 17 rlock = true ; /* release rlock */ 18 od ; 19 waiting [0] = 0 20 enable (0); 21 :: else 22 fi ; 23 unlock ( listlock )} The reader process first obtains the rlock flag to protect from races between multiple readers, then blocks until an item becomes available in the channel, then gets the item from the pipe (in the critical section), then announces the item has been read, then releases the rlock flag. The writer process is declared in a similar style to the read process. The writer process first obtains the wlock flag to protect from races between multiple writers, then places an item in the channel, then makes the item available for the reader, then blocks until the item has been read, and finally releases the wlock. 1 active [ N ] proctype writer () 2 { ( wlock ) -> wlock = false ; 3 write (); 4 printf ( " % d finished writing n " , _pid ); 5 wlock = true ; 6 skip } 7 8 inline write ( block ) 9 { if 10 :: atomic { select -> printf ( " 1 st time acquire n " ); } -> 11 goto endd 12 :: else 13 fi ; 14 if 15 :: ! block -> goto endd
  • 18. 18 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 16 :: else 17 fi ; 18 semqueue (); 19 do 20 :: skip -> 21 waiting [ _pid ] = 1; 22 if 23 :: atomic { select -> printf ( " not 1 st time acquire n " ); 24 } -> 25 break 26 :: else 27 fi ; 28 disable ( semaenabled ()) 29 od ; 30 semdequeue (); 31 endd : 32 do 33 :: ( wlock ) -> wlock = false ; /* obtain wlock */ 34 s_c ! msg ; /* place item in pipe critical section */ 35 available ++; /* release available */ 36 atomic { taken > 0; 37 taken -- /* acquire taken */} 38 wlock = true ; /* release wlock */ 39 od ; 40 assert (! block || selected [ _pid ]); 41 assert selected [ _pid ]; 42 assert ! waiting [ _pid ]; 43 printf ( " % d done n " , _pid );} The channel algorithm used in this model is defined as: 1 chan s_c = [0] of { mtype }; /* rendezvous channel */ 2 chan c_r = [0] of { mtype }; 3 4 active proctype pipe () 5 { mtype m ; 6 do 7 :: s_c ? m -> c_r ! m 8 od } The first two statements declare sc and cr to be channels. These will provide commu- nication to write into or read from the pipe, with no buffering capacity (i.e., communication
  • 19. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 19 will be via rendezvous) that carries messages consisting of a byte (mtype). The body of the do-loop retrieves the received message and stores it into the local variable m on the receiver side. The data is always stored in empty channels and is always retrieved from full channels. The ALT process manages three different arrays to store and change the status of various read and write processes. Each process can be in one of the following states: waiting[N]: the process is ready to synchronise disabled[N]: the process should not attempt to synchronise and should roll back from an enable call to the previous state is_selectable[N]: is true if the guard is able to complete a synchronous transaction selected[N]: the process should complete a synchronous transaction (write-read) The process can only read and change its state in the array after it completes a transaction such as read or write. The ALT process can also change the state of various processes. For example, the ALT process can select two processes to synchronise and disable all other processes. This state space management implementation is simpler than exchanging messages between the ALT and read or write processes to set or read processes states that is required to accomplish a read-write synchronisation transaction. The exchange of state messages makes the model complex and requires careful synchronisation. Nevertheless, since more than one process can access the array a listlock semaphore was implemented to prevent races between multiple processes. 1 inline lock ( x ) 2 { atomic { x == 0; x = 1 }} 3 4 inline unlock ( x ) 5 { assert x ==1; x = 0} 6 7 lock ( listlock ); 8 unlock ( listlock ); The ALT process pushes the selectable process, ready to complete a synchronisation trans- action, into a queue before the synchronisation starts (dequeue). This implementation will make any future improvements or modifications to the nondeterministic selection procedure easy to model. For example, the ALT can use various nondeterministic selection methods such as priority select or fair select. 1 inline semqueue () 2 { lock ( listlock ); 3 assert ! is_selectable [ _pid ]; 4 is_selectable [ _pid ] = 1; 5 unlock ( listlock )} 6 7 inline semdequeue () 8 { lock ( listlock ); 9 assert is_selectable [ _pid ]; 10 is_selectable [ _pid ] = 0; 11 waiting [ _pid ] = 0; 12 unlock ( listlock )}
  • 20. 20 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython Firstly, the model was run in SPIN random simulation mode. SPIN simulator enables users to gain early feedback on their system models that helps in the development of the designers understanding of the design space before they advance in any formal analysis. However, SPIN provides a limited form of support for verification in terms of assertion checking, i.e. the checking of local and global system properties during simulation runs. For example, a process called monitor was devoted to assert that a read process will not be executed if the buffer is empty and the buffer can not be overwritten by write process before the read process is executed. 1 proctype monitor () 2 { do 3 :: assert ( taken <2) ; 4 :: assert ( available <2); 5 od } Figure 2. Message sequence chart of SPIN model checker showing two readers and two writers. Figure ?? shows the Message Sequence Chart (MSC) Panel. Each process is associated with a vertical line where the ”start of time” corresponds to the top of the MSC moving down with the vertical distance represents the relative time between different temporal events. The message passing is represented by the relative ordering of arrows between process execution lines. SPIN verification mode is used to verify liveness and safety properties like deadlock de- tection, invariants or code reachability. Verification parameters are set to enable check for ”invalid endstates” in the model. 1 spin -a py - csp . p 2 pcc - DSAFETY - DREACH - D M E M L I M = 500 -O pan pan . c 3 pan -i 4 rm pan .* pan
  • 21. S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython 21 The verification output does not show any output referring to ”invalid end states” which means that the verification has passed. 5. Conclusions and future work python-csp provides a “Pythonic” library for the structuring of concurrent programs in a CSP style. This provides an alternative to the event-driven style which has become preva- lent with the increasing popularity of object oriented methods. python-csp realises the three fundamental concepts of CSP, processes, synchronous channel communication and non- determnistic choice, for use both explicitly and with appropriate syntactic sugar to provide program texts with much more of the ’look and feel’ of CSP. python-csp has been realised as a number of distinct realisations. One notable imple- mentation is jython-csp, which, as a result of Jython’s reliance on the Java Virtual Machine, yields a platform independent implementation. As an example of a real program, parallelised using python-csp, the Mandelbrot gener- ator has been presented. Both a producer/consumer and worker/farmer implementation have been described, and the worker/farmer shows a linear performance relationship with number of processes used (running on a dual-core computer). The correctness of channel synchronisation in python-csp has been demonstrated using a model checker. Future work will include a study of the correctness of non-deterministic selection in python-csp. Evaluation of the performance of python-csp shows that it performs slightly faster than equivalent implementations of PyCSP (significantly faster for the OS process version). The motivation for the constriction of python-csp was to provide a syntactically nat- ural and semantically robust framework for the design and implementation of large scale, distributed, parallel systems, in particular wireless sensor networks. It is hoped that such systems will one day be grounded in a secure theory of communication and concurrency. python-csp has provided such a framework, but is so far limited to a shared memory, sin- gle machine implementation. The next stages in this work are to extend the synchronised communications to operate over inter-machine communications links. In some ways, CSP communications, being already modelled on a ’channel’, are ideal for such a purpose. On the other hand, real communications channels, particularly wireless ones, have quite different characteristics from the instantaneous and reliable CSP channel. Finding efficient means for duplicating the semantics of the CSP channel using real communications remains a challenge for the authors. Acknowledgements The authors wish to acknowledge the Nuffield Foundation’s support for this research through an Undergraduate Research Bursary (URB/37018), which supported the work of the third author. References [1] Tim Peters. PEP20 the zen of python. http://www.python.org/dev/peps/pep-0020/, August 2004. [2] Christian Tismer. Continuations and stackless python or ”how to change a paradigm of an existing pro- gram”. In In Proceedings of the 8th International Python Conference, January 2000. [3] C.A.R. Hoare. Communicating Sequential Processes. Prentice-Hall, London, 1985. ISBN: 0-131-53271- 5.
  • 22. 22 S. Mount et al. / CSP as a Domain-Specific Language Embedded in Python and Jython [4] S.N.I. Mount, R.M. Newman, and E.I. Gaura. A simulation tool for system services in ad-hoc wireless sensor networks. In In Proceedings of NSTI Nanotechnology Conference and Trade Show (Nanotech’05), volume 3, pages 423–426, Anaheim, California, USA, May 2005. [5] S. Mount, R.M. Newman, E. Gaura, and J. Kemp. Sensor: an algorithmic simulator for wireless sensor networks. In In Proceedings of Eurosensors 20, volume II, pages 400–411, Gothenburg, Sweden, 2006. [6] John Markus Bjørndalen, Brian Vinter, and Otto J. Anshus. PyCSP - Communicating Sequential Processes for Python. In Alistair A. McEwan, Wilson Ifill, and Peter H. Welch, editors, Communicating Process Architectures 2007, pages 229–248, jul 2007. [7] P.H.Welch. Process Oriented Design for Java: Concurrency for All. In H.R.Arabnia, editor, Proceed- ings of the International Conference on Parallel and Distributed Processing Techniques and Applications (PDPTA’2000), volume 1, pages 51–57. CSREA, CSREA Press, June 2000. [8] N.C.C. Brown and P.H. Welch. An introduction to the Kent C++CSP library. In J.F. Broenink and G.H. Hilderink, editors, Communicating Process Architectures 2003, volume 61 of Concurrent Systems Engi- neering Series, pages 139–156, Amsterdam, The Netherlands, September 2003. IOS Press. [9] Bernhard H. C. Sputh and Alastair R. Allen. Jcsp-poison: Safe termination of csp process networks. In Jan F. Broenink, Herman W. Roebbers, Johan P. E. Sunter, Peter H. Welch, and David C. Wood, editors, CPA, volume 63 of Concurrent Systems Engineering Series, pages 71–107. IOS Press, 2005. [10] P.H. Welch. Graceful Termination – Graceful Resetting. In Applying Transputer-Based Parallel Machines, Proceedings of OUG 10, pages 310–317, Enschede, Netherlands, April 1989. Occam User Group, IOS Press, Netherlands. ISBN 90 5199 007 3. [11] Peter H. Welch and Fred R.M. Barnes. Communicating mobile processes: introducing occam-pi. In A.E. Abdallah, C.B. Jones, and J.W. Sanders, editors, 25 Years of CSP, volume 3525 of Lecture Notes in Computer Science, pages 175–210. Springer Verlag, April 2005. [12] Gerard J. Holzmann. The model checker SPIN. IEEE Transactions on Software Engineering, 23:279–295, 1997.