├── .hgignore
├── ChangeLog
├── IRClogs
└── Europython2010Sprint.log
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.md
├── applications
└── python-csp.desktop
├── benchmark
├── commstime
│ ├── commstime.mcsp
│ └── commstime.py
└── tokenring
│ ├── plot_results.py
│ └── tokenring.py
├── csp
├── __init__.py
├── builtins.py
├── cchannels
│ ├── CChannel.py
│ ├── Channel.c
│ ├── Channel.h
│ ├── Channel.i
│ ├── Channel.py
│ ├── Channel_wrap.c
│ ├── Makefile
│ └── tests
│ │ ├── commstime.py
│ │ ├── fulladder.py
│ │ ├── patterns.py
│ │ ├── simple.py
│ │ └── tokenring.py
├── csp.py
├── dsp.py
├── guards.py
├── lint
│ ├── __init__.py
│ ├── channels.py
│ ├── lint.py
│ └── processes.py
├── os_process.py
├── os_thread.py
├── patterns.py
└── tracer
│ ├── __init__.py
│ ├── cspmodel.py
│ └── tracer.py
├── docs
├── doctrees
│ ├── builtins.doctree
│ ├── csp.doctree
│ ├── environment.pickle
│ ├── guards.doctree
│ ├── index.doctree
│ ├── mandelbrot.doctree
│ ├── patterns.doctree
│ └── tracer.doctree
└── html
│ ├── .buildinfo
│ ├── _sources
│ ├── builtins.txt
│ ├── csp.txt
│ ├── guards.txt
│ ├── index.txt
│ ├── mandelbrot.txt
│ ├── patterns.txt
│ └── tracer.txt
│ ├── _static
│ ├── basic.css
│ ├── default.css
│ ├── doctools.js
│ ├── file.png
│ ├── jquery.js
│ ├── minus.png
│ ├── plus.png
│ ├── pygments.css
│ ├── pythoncsp-docs.png
│ └── searchtools.js
│ ├── builtins.html
│ ├── csp.html
│ ├── genindex.html
│ ├── guards.html
│ ├── index.html
│ ├── mandelbrot.html
│ ├── modindex.html
│ ├── objects.inv
│ ├── patterns.html
│ ├── search.html
│ ├── searchindex.js
│ └── tracer.html
├── examples
├── barber
│ ├── barber.py
│ ├── kbox.occ
│ └── queue.py
├── boids
│ ├── boidprocs-obstacles.dia
│ ├── boidprocs.dia
│ ├── boids-part1.png
│ ├── boids-part2.png
│ ├── boids-part3.png
│ ├── boids-part4.png
│ ├── boids-sliders.png
│ ├── part1-classes.png
│ ├── part1.py
│ ├── part2-classes.png
│ ├── part2.py
│ ├── part3-classes.png
│ ├── part3.py
│ ├── part4-classes.png
│ ├── part4-sliders.py
│ └── part4.py
├── builtins
│ └── builtin-example.py
├── circuits
│ └── fulladder.py
├── mandelbrot
│ ├── mandelbrot-WorkerFarmer.py
│ ├── mandelbrot-noalt.py
│ ├── mandelbrot-onech.py
│ └── mandelbrot.py
├── matrix
│ └── matrix.py
├── monte_carlo
│ └── pi.py
├── raytracer
│ └── raytracer.py
└── sensors
│ ├── dsp.py
│ ├── hidsensor.py
│ ├── oak_oscope.py
│ ├── oscilloscope.py
│ ├── toradex.py
│ └── toradex_csp.py
├── exstatic
├── __init__.py
├── cspwarnings.py
├── icode.py
├── py2icode.py
├── stack.py
├── visitor.py
└── warnings.py
├── gadget
└── readme.xml
├── logo
├── logo-square.png
├── pythoncsp-docs.png
├── pythoncsp-logo.png
└── pythoncsp-logo.xcf
├── make.bat
├── maketags.sh
├── rst
├── Tutorial.wiki
├── TutorialPage0.wiki
├── TutorialPage1.wiki
├── TutorialPage2.wiki
├── TutorialPage3.wiki
├── TutorialPage4.wiki
├── TutorialPage5.wiki
├── TutorialPage7.wiki
├── TutorialPage8.wiki
├── builtins.rst
├── conf.py
├── csp.rst
├── guards.rst
├── index.rst
├── mandelbrot.rst
└── patterns.rst
├── scripts
├── cspdb
├── csplint
└── python-csp
├── setup.cfg
├── setup.py
├── test
├── test_builtins.py
├── test_contexts.py
├── test_forever.py
├── test_tracer.py
├── testcsp.py
├── testpar.py
├── testrep.py
├── testsock.py
└── winder_bug
│ ├── pi_python_python-csp_multiple_nested_deep.py
│ ├── pi_python_python-csp_multiple_nested_shallow.py
│ ├── pi_python_python-csp_multiple_separate.py
│ ├── pi_python_python-csp_single_nested_deep.py
│ ├── pi_python_python-csp_single_nested_shallow.py
│ └── pi_python_python-csp_single_separate.py
└── tutorial
├── README
├── part01
└── webserver.py
├── part02
└── filecount.py
├── part03
└── mandelbrot.py
├── part04
└── shop.py
├── part07
├── Oscilloscope.png
├── oscilloscope.py
└── traces.py
└── part08
├── Queue.dia
└── Queue.png
/.hgignore:
--------------------------------------------------------------------------------
1 | TAGS
2 | python_csp.egg-info
3 | build
4 | dist
5 | syntax: glob
6 | *.pyc
7 | examples/mandelbrot/mandelbrot.png
8 |
--------------------------------------------------------------------------------
/ChangeLog:
--------------------------------------------------------------------------------
1 | 8 May 2010
2 | Introduced documented readsets and writesets. Added lint-like
3 | static checker to determine whether readsets and writesets are
4 | correctly documented.
5 | 2 May 2010
6 | Introduced CSPServer processes and a @forever decorator to easily
7 | create them.
8 | 1 May 2010
9 | Removed the _process keyword from CSPProcess objects.
10 | Refactored builtin processes to their own library.
11 | Updated documentation in the python-csp shell.
12 | 9 Apr 2010:
13 | Moved documentation to Sphinx.
14 | Added new project logo.
15 | 6 Apr 2010:
16 | Added packages for bulk synchronous processing and reactive
17 | programming. Added directory structure for tutorial examples.
18 | 15 Nov 2009:
19 | Major poisoning bug fixed. Other bug fixes in test scripts and
20 | synchronisation fixed.
21 | 9 Nov 2009:
22 | Added token ring example to benchmark/ directory. Added bsp
23 | package containing barriers. These are automatically imported into
24 | csp modules.
25 | 26 Oct 2009:
26 | Added Boids demo to the examples/ directory.
27 | 28 June 2009:
28 | Added unit testing, in addition to test scripts. Sam Wilson added
29 | Jython version of the CSP library / DSL.
30 | 20 June 2009:
31 | Added threaded version of python-csp. Made main CSP code PEP8
32 | compliant.
33 | 24 March 2009:
34 | Fixed bug in channel poisoning.
35 | 6 January 2009:
36 | Added ALTing to CSP package. Added example parallel programs,
37 | including Mandelbrot fractal generator.
38 | 22 December 2008:
39 | Added initial version of CSP package. Added python-csp
40 | shell. Added .desktop files for GNU/Linux desktop integration.
41 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README ChangeLog LICENSE
2 | include scripts/python-csp
3 | include scripts/cspdb
4 |
5 | recursive-include csp/ *.py
6 | recursive-include exstatic/ *.py
7 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | RST = rst
5 | BUILD = docs
6 |
7 | # You can set these variables from the command line.
8 | SPHINXOPTS = $(RST)
9 | SPHINXBUILD = sphinx-build
10 | PAPER = a4
11 |
12 | # Internal variables.
13 | PAPEROPT_a4 = -D latex_paper_size=a4
14 | PAPEROPT_letter = -D latex_paper_size=letter
15 | ALLSPHINXOPTS = -d $(BUILD)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS)
16 |
17 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " pickle to make pickle files"
24 | @echo " json to make JSON files"
25 | @echo " htmlhelp to make HTML files and a HTML help project"
26 | @echo " qthelp to make HTML files and a qthelp project"
27 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
28 | @echo " changes to make an overview of all changed/added/deprecated items"
29 | @echo " linkcheck to check all external links for integrity"
30 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
31 |
32 | clean:
33 | -rm -rf $(BUILD)/*
34 |
35 | html:
36 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILD)/html
37 | @echo
38 | @echo "Build finished. The HTML pages are in $(BUILD)/html."
39 |
40 | dirhtml:
41 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILD)/dirhtml
42 | @echo
43 | @echo "Build finished. The HTML pages are in $(BUILD)/dirhtml."
44 |
45 | pickle:
46 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILD)/pickle
47 | @echo
48 | @echo "Build finished; now you can process the pickle files."
49 |
50 | json:
51 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILD)/json
52 | @echo
53 | @echo "Build finished; now you can process the JSON files."
54 |
55 | htmlhelp:
56 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILD)/htmlhelp
57 | @echo
58 | @echo "Build finished; now you can run HTML Help Workshop with the" \
59 | ".hhp project file in $(BUILD)/htmlhelp."
60 |
61 | qthelp:
62 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILD)/qthelp
63 | @echo
64 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
65 | ".qhcp project file in $(BUILD)/qthelp, like this:"
66 | @echo "# qcollectiongenerator $(BUILD)/qthelp/python-csp.qhcp"
67 | @echo "To view the help file:"
68 | @echo "# assistant -collectionFile $(BUILD)/qthelp/python-csp.qhc"
69 |
70 | latex:
71 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILD)/latex
72 | @echo
73 | @echo "Build finished; the LaTeX files are in $(BUILD)/latex."
74 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
75 | "run these through (pdf)latex."
76 |
77 | changes:
78 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILD)/changes
79 | @echo
80 | @echo "The overview file is in $(BUILD)/changes."
81 |
82 | linkcheck:
83 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILD)/linkcheck
84 | @echo
85 | @echo "Link check complete; look for any errors in the above output " \
86 | "or in $(BUILD)/linkcheck/output.txt."
87 |
88 | doctest:
89 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILD)/doctest
90 | @echo "Testing of doctests in the sources finished, look at the " \
91 | "results in $(BUILD)/doctest/output.txt."
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | python-csp: Communicating Sequential Processes for Python
2 | =========================================================
3 |
4 | Copyright (C) Sarah Mount, 2009 under the GNU GPL v2. See the file LICENSE for
5 | more details.
6 |
7 | Installation
8 | ------------
9 |
10 | python-csp can be installed using PIP (PIP Installs Python):
11 |
12 | $ sudo pip install python-csp
13 |
14 | or from a source distribution using setup.py:
15 |
16 | $ sudo python setup.py install
17 |
18 |
19 | Introduction
20 | ------------
21 |
22 | python-csp adds C.A.R. (Tony) Hoare's Communicating Sequential Processes to
23 | Python. A brief example:
24 |
25 | ```python
26 | >>> @process
27 | ... def writer(channel, n):
28 | ... for i in xrange(n):
29 | ... channel.write(i)
30 | ... channel.poison()
31 | ... return
32 | ...
33 | >>> @process
34 | ... def reader(channel):
35 | ... while True:
36 | ... print channel.read()
37 | ...
38 | >>> chan = Channel()
39 | >>> Par(reader(chan), writer(chan, 5)).start()
40 | 0
41 | 1
42 | 2
43 | 3
44 | 4
45 | >>>
46 | ```
47 |
48 | Documentation.
49 | -------------
50 |
51 | There are several sources of documentation for python-csp:
52 |
53 | * If you are running the python-csp shell, type "info csp" to list available in-shell help.
54 |
55 | * A user guide exists in the `tutorial/` directory of the source.
56 |
57 | * `examples/` contains some larger example programs.
58 |
59 |
60 | Publications.
61 | ------------
62 |
63 | S. Mount, M. Hammoudeh, S. Wilson, R. Newman (2009) CSP as a Domain-Specific
64 | Language Embedded in Python and Jython. In Proceedings of Communicating Process
65 | Architectures 2009. Eindoven, Netherlands. 1st -- 4th November 2009. Published
66 | IOS Press.
67 |
--------------------------------------------------------------------------------
/applications/python-csp.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Python-CSP
3 | Comment=Communicating Sequential Processes in Python
4 | Exec=/usr/bin/python-csp
5 | Icon=/usr/share/pixmaps/python.xpm
6 | Terminal=true
7 | MultipleArgs=false
8 | Type=Application
9 | Categories=Application;Development;
10 | StartupNotify=true
11 |
--------------------------------------------------------------------------------
/benchmark/commstime/commstime.mcsp:
--------------------------------------------------------------------------------
1 | PREFIX (in,out) ::= out -> @x.(in -> out -> x)
2 | SUCC (in,out) ::= @x.(in -> out -> x)
3 | DELTA (in,out1,out2) ::= @x.(in -> out1 -> out2 -> x)
4 | CONSUME (in,report) ::= @x.((;[i=1,1000000] in); report -> x)
5 | SYSTEM (report) ::= ((PREFIX (a, b) || DELTA (b, c, d)) ||
6 | (SUCC (c, a) || CONSUME (d, report))) \ {a,b,c,d}
7 |
8 |
--------------------------------------------------------------------------------
/benchmark/commstime/commstime.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """CSP Commstime benchmark.
3 |
4 | See F.R.M. Barnes (2006) Compiling CSP. In Proceedings of
5 | Communicating Process Architectures 2006.
6 |
7 | Code adapted from PyCSP by John Markus Bjorndalen, available:
8 | http://www.cs.uit.no/~johnm/code/PyCSP/
9 |
10 | PyCSP - Communicating Sequential Processes for Python. John Markus
11 | Bjorndalen, Brian Vinter, Otto Anshus. CPA 2007, Surrey, UK, July
12 | 8-11, 2007. IOS Press 2007, ISBN 978-1-58603-767-3, Concurrent
13 | Systems Engineering Series (ISSN 1383-7575).
14 | """
15 |
16 | from csp.csp import *
17 | from csp.builtins import Prefix, Delta2, Succ
18 |
19 | import os
20 | import time
21 |
22 | @process
23 | def Consumer(cin):
24 | """Commstime consumer process
25 |
26 | readset = cin
27 | writeset =
28 | """
29 | N = 5000
30 | ts = time.time
31 | t1 = ts()
32 | cin.read()
33 | t1 = ts()
34 | for i in range(N):
35 | cin.read()
36 | t2 = ts()
37 | dt = t2-t1
38 | tchan = dt / (4 * N)
39 | print("DT = {0}.\nTime per ch : {1}/(4*{2}) = {3} s = {4} us".format(dt, dt, N, tchan, tchan * 1000000))
40 | print("consumer done, posioning channel")
41 | cin.poison()
42 |
43 | def CommsTimeBM():
44 | print('Creating channels now...')
45 | # Create channels
46 | a = Channel()
47 | b = Channel()
48 | c = Channel()
49 | d = Channel()
50 | print("Running commstime test")
51 | Par(Prefix(c, a, prefix_item = 0), # Initiator
52 | Delta2(a, b, d), # Forwarding to two
53 | Succ(b, c), # Feeding back to prefix
54 | Consumer(d)).start() # Timing process
55 | print('Finished run...')
56 |
57 |
58 | if __name__ == '__main__':
59 | N_BM = 10
60 | for i in range(N_BM):
61 | print("----------- run {0}/{1} -------------".format(i+1, N_BM))
62 | CommsTimeBM()
63 | print("------- Commstime finished ---------")
64 |
--------------------------------------------------------------------------------
/benchmark/tokenring/plot_results.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Plotting results of variable ring buffer experiment.
5 |
6 | Copyright (C) Sarah Mount, 2009.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program; if not, write to the Free Software
20 | """
21 |
22 | from scipy import *
23 | from pylab import *
24 |
25 | __author__ = 'Sarah Mount '
26 | __date__ = 'November 2009'
27 |
28 | FILENAME = 'token_ring.png'
29 |
30 | subplots_adjust(hspace=0.4, wspace=0.6)
31 |
32 | # Num of nodes in token ring
33 | t = array([2, 4, 8, 16, 32, 64, 128, 256, 512, 1024])
34 |
35 |
36 | yvals = {1:{'procs':array([350.057995,
37 | 314.430736, 157.215372, 78.607687, 39.303844,
38 | 19.651922, 9.825962, 4.912981, 2.456491, None, None]),
39 | 'threads':array([314.430851, 157.215429, 78.607716, 39.303859,
40 | 19.651930, 9.825965, 4.912983, 2.456492, None, None]),
41 | 'jython':array([314.431448, 157.215729, 78.607867, 39.303935,
42 | 19.651969, 9.825985, 4.912993, 2.456502, 1.228249, 0.614125])}
43 | }
44 |
45 |
46 | subplot(111)
47 | title('Variable sized ring buffer \nwith one token')
48 | plot(t, yvals[1]['procs'], 'g^-')
49 | plot(t, yvals[1]['threads'], 'k*--')
50 | plot(t, yvals[1]['jython'], 'rx-.')
51 |
52 | legend(['Processes reified as OS processes',
53 | 'Processes reified as OS threads',
54 | 'Processes reified as Java threads'],
55 | loc='upper left')
56 |
57 | xlabel('Number of nodes in token ring')
58 | ylabel(r'Time $(\mu{}s)$')
59 |
60 | ###
61 |
62 | #subplot(222)
63 | #title('16 node ring buffer \nwith three tokens')
64 | #plot(t, yvals[1]['procs'], 'g^-')
65 | #plot(t, yvals[1]['threads'], 'k*--')
66 | #plot(t, yvals[1]['jython'], 'rx-.')
67 |
68 | #legend(['Processes reified as OS processes',
69 | # 'Processes reified as OS threads',
70 | # 'Processes reified as Java threads'],
71 | # loc='upper left')
72 |
73 | #xlabel('Number of nodes in token ring')
74 | #ylabel(r'Time $(\mu{}s)$')
75 |
76 | ###
77 |
78 | #subplot(223)
79 | #title('32 node ring buffer \nwith three tokens')
80 | #plot(t, yvals[1]['procs'], 'g^-')
81 | #plot(t, yvals[1]['threads'], 'k*--')
82 | #plot(t, yvals[1]['jython'], 'rx-.')
83 |
84 | #legend(['Processes reified as OS processes',
85 | # 'Processes reified as OS threads',
86 | # 'Processes reified as Java threads'],
87 | # loc='upper left')
88 |
89 | #xlabel('Number of nodes in token ring')
90 | #ylabel(r'Time $(\mu{}s)$')
91 |
92 | ###
93 |
94 | #subplot(224)
95 | #title('64 node ring buffer \nwith three tokens')
96 | #plot(t, yvals[1]['procs'], 'g^-')
97 | #plot(t, yvals[1]['threads'], 'k*--')
98 | #plot(t, yvals[1]['jython'], 'rx-.')
99 |
100 | #legend(['Processes reified as OS processes',
101 | # 'Processes reified as OS threads',
102 | # 'Processes reified as Java threads'],
103 | # loc='upper left')
104 |
105 | #xlabel('Number of nodes in token ring')
106 | #ylabel(r'Time $(\mu{}s)$')
107 |
108 | ###
109 |
110 | grid(True)
111 | savefig(FILENAME, format='png')
112 | show()
113 |
--------------------------------------------------------------------------------
/benchmark/tokenring/tokenring.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Benchmark based on variable sized ring buffer.
5 | See also PyCSP papers in CPA2009 proceedings.
6 |
7 | Usage: tokenring-processes.py [options]
8 |
9 | Options:
10 | -h, --help show this help message and exit
11 | -t TOKENS, --tokens=TOKENS
12 | Number of tokens in token ring
13 | -n NODES, --nodes=NODES
14 | Number of nodes in token ring
15 | -x, --experiment Experimental mode. Run 10 token rings with nodes 2^1
16 | to 2^10 and print results
17 |
18 | Copyright (C) Sarah Mount, 2009.
19 |
20 | This program is free software; you can redistribute it and/or
21 | modify it under the terms of the GNU General Public License
22 | as published by the Free Software Foundation; either version 2
23 | of the License, or (at your option) any later version.
24 |
25 | This program is distributed in the hope that it will be useful,
26 | but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 | GNU General Public License for more details.
29 |
30 | You should have rceeived a copy of the GNU General Public License
31 | along with this program; if not, write to the Free Software
32 |
33 | """
34 |
35 | __author__ = 'Sarah Mount '
36 | __date__ = 'November 2009'
37 |
38 | from csp.csp import *
39 | from csp.patterns import TokenRing
40 |
41 |
42 | TRIALS = 10000
43 |
44 |
45 | @process
46 | def ringproc(index=0, numnodes=64, tokens=1, inchan=None, outchan=None):
47 | """
48 | readset = inchan
49 | writeset = outchan
50 | """
51 | if tokens == 1 and index == 0:
52 | token = 1
53 | outchan.write(token)
54 | for i in range(TRIALS):
55 | token = inchan.read()
56 | token += 1
57 | outchan.write(token)
58 | # Avoid deadlock.
59 | if index == 1:
60 | inchan.read()
61 |
62 |
63 | if __name__ == '__main__':
64 | from optparse import OptionParser
65 |
66 | parser = OptionParser()
67 |
68 | parser.add_option('-t', '--tokens', dest='tokens',
69 | action='store', type="int",
70 | default=1,
71 | help='Number of tokens in token ring')
72 | parser.add_option('-n', '--nodes', dest='nodes',
73 | action='store', type="int",
74 | default=64,
75 | help='Number of nodes in token ring')
76 | parser.add_option('-x', '--experiment', dest='exp',
77 | action='store_true', default=False,
78 | help=('Experimental mode. Run 10 token rings with nodes '
79 | + '2^1 to 2^10 and print results'))
80 |
81 | (options, args) = parser.parse_args()
82 |
83 | if options.exp:
84 | print('All times measured in microseconds.')
85 | for size in range(2, 10):
86 | try:
87 | print('Token ring with {0} nodes.'.format(size))
88 | starttime = time.time()
89 | TokenRing(ringproc, 2 ** size, numtoks=options.tokens).start()
90 | elapsed = time.time() - starttime
91 | mu = elapsed * 1000000 / float((TRIALS * (2 ** size)))
92 | print('{0}ms'.format(mu))
93 | except:
94 | continue
95 | else:
96 | import time
97 | print 'Token ring with {0} nodes and {1} token(s).'.format(options.nodes, options.tokens)
98 | starttime = time.time()
99 | TokenRing(ringproc, options.nodes, numtoks=options.tokens).start()
100 | elapsed = time.time() - starttime
101 | mu = elapsed * 1000000 / float((TRIALS * (2 ** options.nodes)))
102 | print '{0}ms'.format(mu)
103 |
--------------------------------------------------------------------------------
/csp/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/csp/__init__.py
--------------------------------------------------------------------------------
/csp/cchannels/CChannel.py:
--------------------------------------------------------------------------------
1 | import Channel as chnl
2 | import cPickle
3 | import uuid
4 | from csp.guards import Guard
5 |
6 | class CChannel(Guard):
7 |
8 | def __init__(self):
9 | p = uuid.uuid4().int & 0xffffff
10 | av = uuid.uuid4().int & 0xffffff
11 | tak = uuid.uuid4().int & 0xffffff
12 | shm = uuid.uuid4().int & 0xffffff
13 |
14 | self.channel = chnl.getChannel(p,av,tak,shm)
15 | self.name = uuid.uuid1()
16 | return
17 |
18 | def __del__(self):
19 | chnl.removeChannel(self.channel)
20 | self.channel = None
21 | return
22 |
23 | def put(self,item):
24 | a = cPickle.dumps(item)
25 | chnl.put(self.channel,a);
26 | return
27 |
28 | def get(self):
29 | chnl.get(self.channel,ret)
30 | item = cPickle.loads(ret)
31 | print(item)
32 | return item
33 |
34 | def is_selectable(self):
35 | #print ( "is_selectable has been called" )
36 | a = chnl.is_selectable(self.channel)
37 | #print ( "is_selectable got ", a )
38 | if a == 1:
39 | return True
40 | else:
41 | return False;
42 |
43 | def write(self,item):
44 | a = cPickle.dumps(item)
45 | chnl._write(self.channel,a,len(a));
46 | return
47 |
48 | def read(self):
49 | print("invoked read")
50 | ret = chnl._read(self.channel)
51 | print(ret)
52 | item = cPickle.loads(ret)
53 | print(item)
54 | return item
55 |
56 | def enable(self):
57 | #print("ENABLED CALLED")
58 | chnl.enable(self.channel)
59 | #print("returning from enable")
60 | return
61 |
62 | def disable(self):
63 | chnl.disable(self.channel)
64 | return
65 |
66 | def select(self):
67 | #print("calling _select")
68 | ret = chnl._select(self.channel)
69 | item = cPickle.loads(ret)
70 | print(item)
71 | return item
72 |
73 | def poison(self):
74 | chnl.poison(self.channel);
75 | return
76 |
77 | def getStatus(self):
78 | chnl.getStatus(self.channel)
79 | return
80 |
81 | def checkpoison(self):
82 | chnl.checkpoison()
83 | return
84 |
--------------------------------------------------------------------------------
/csp/cchannels/Channel.h:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #define false 0
12 | #define true (!false)
13 |
14 | typedef struct{
15 | pthread_mutex_t r_lock;
16 | pthread_mutex_t w_lock;
17 | key_t p_lock_key;
18 | int p_lock;
19 | key_t available_key;
20 | int available;
21 | key_t taken_key;
22 | int taken;
23 | unsigned int is_alting;
24 | unsigned int is_selectable;
25 | unsigned int has_selected;
26 | unsigned int poisoned;
27 | char* item;
28 | key_t sh_mem_name;
29 | //char *shm;
30 | int shmid;
31 | int len;
32 |
33 | }Channel;
34 |
35 | union semun {
36 | int val;
37 | struct semid_ds *buf;
38 | ushort *array;
39 | };
40 |
--------------------------------------------------------------------------------
/csp/cchannels/Channel.i:
--------------------------------------------------------------------------------
1 | /* Channel.i */
2 | %module Channel
3 | %{
4 | #include
5 | #include
6 | #include "Channel.h"
7 |
8 | extern int sq(int i);
9 | extern void getStatus(Channel *c);
10 | extern Channel getChannel(long int p,long int av,long int tak,long int shm);
11 | extern void removeChannel(Channel *c);
12 | extern void checkpoison(Channel *c);
13 | extern void put(Channel *c, char *ptr, int len);
14 | extern void get(Channel *c, char *ptr);
15 | extern int is_selectable(Channel *c);
16 | extern void _write(Channel *c, char *ptr,int len);
17 | extern char *_read(Channel *c);
18 | extern void enable(Channel *c);
19 | extern void disable(Channel *c);
20 | extern char *_select(Channel *c);
21 | extern void poison(Channel *c);
22 |
23 | %}
24 |
25 |
26 | extern int sq(int i);
27 | extern void getStatus(Channel *c);
28 | extern Channel getChannel(long int p,long int av,long int tak,long int shm);
29 | extern void removeChannel(Channel *c);
30 | extern void checkpoison(Channel *c);
31 | extern void put(Channel *c, char *ptr, int len);
32 | extern void get(Channel *c, char *ptr);
33 | extern int is_selectable(Channel *c);
34 | extern void _write(Channel *c, char *ptr,int len);
35 | extern char *_read(Channel *c);
36 | extern void enable(Channel *c);
37 | extern void disable(Channel *c);
38 | extern char *_select(Channel *c);
39 | extern void poison(Channel *c);
40 |
--------------------------------------------------------------------------------
/csp/cchannels/Channel.py:
--------------------------------------------------------------------------------
1 | # This file was automatically generated by SWIG (http://www.swig.org).
2 | # Version 1.3.40
3 | #
4 | # Do not make changes to this file unless you know what you are doing--modify
5 | # the SWIG interface file instead.
6 | # This file is compatible with both classic and new-style classes.
7 |
8 | from sys import version_info
9 | if version_info >= (2,6,0):
10 | def swig_import_helper():
11 | from os.path import dirname
12 | import imp
13 | fp = None
14 | try:
15 | fp, pathname, description = imp.find_module('_Channel', [dirname(__file__)])
16 | except ImportError:
17 | import _Channel
18 | return _Channel
19 | if fp is not None:
20 | try:
21 | _mod = imp.load_module('_Channel', fp, pathname, description)
22 | finally:
23 | fp.close()
24 | return _mod
25 | _Channel = swig_import_helper()
26 | del swig_import_helper
27 | else:
28 | import _Channel
29 | del version_info
30 | try:
31 | _swig_property = property
32 | except NameError:
33 | pass # Python < 2.2 doesn't have 'property'.
34 | def _swig_setattr_nondynamic(self,class_type,name,value,static=1):
35 | if (name == "thisown"): return self.this.own(value)
36 | if (name == "this"):
37 | if type(value).__name__ == 'SwigPyObject':
38 | self.__dict__[name] = value
39 | return
40 | method = class_type.__swig_setmethods__.get(name,None)
41 | if method: return method(self,value)
42 | if (not static) or hasattr(self,name):
43 | self.__dict__[name] = value
44 | else:
45 | raise AttributeError("You cannot add attributes to {0}".format(self))
46 |
47 | def _swig_setattr(self,class_type,name,value):
48 | return _swig_setattr_nondynamic(self,class_type,name,value,0)
49 |
50 | def _swig_getattr(self,class_type,name):
51 | if (name == "thisown"): return self.this.own()
52 | method = class_type.__swig_getmethods__.get(name,None)
53 | if method: return method(self)
54 | raise AttributeError(name)
55 |
56 | def _swig_repr(self):
57 | try: strthis = "proxy of " + self.this.__repr__()
58 | except: strthis = ""
59 | return "<{0}.{1}; {2} >".format(self.__class__.__module__, self.__class__.__name__, strthis)
60 |
61 | try:
62 | _object = object
63 | _newclass = 1
64 | except AttributeError:
65 | class _object : pass
66 | _newclass = 0
67 |
68 |
69 |
70 | def sq(*args):
71 | return _Channel.sq(*args)
72 | sq = _Channel.sq
73 |
74 | def getStatus(*args):
75 | return _Channel.getStatus(*args)
76 | getStatus = _Channel.getStatus
77 |
78 | def getChannel(*args):
79 | return _Channel.getChannel(*args)
80 | getChannel = _Channel.getChannel
81 |
82 | def removeChannel(*args):
83 | return _Channel.removeChannel(*args)
84 | removeChannel = _Channel.removeChannel
85 |
86 | def checkpoison(*args):
87 | return _Channel.checkpoison(*args)
88 | checkpoison = _Channel.checkpoison
89 |
90 | def put(*args):
91 | return _Channel.put(*args)
92 | put = _Channel.put
93 |
94 | def get(*args):
95 | return _Channel.get(*args)
96 | get = _Channel.get
97 |
98 | def is_selectable(*args):
99 | return _Channel.is_selectable(*args)
100 | is_selectable = _Channel.is_selectable
101 |
102 | def _write(*args):
103 | return _Channel._write(*args)
104 | _write = _Channel._write
105 |
106 | def _read(*args):
107 | return _Channel._read(*args)
108 | _read = _Channel._read
109 |
110 | def enable(*args):
111 | return _Channel.enable(*args)
112 | enable = _Channel.enable
113 |
114 | def disable(*args):
115 | return _Channel.disable(*args)
116 | disable = _Channel.disable
117 |
118 | def _select(*args):
119 | return _Channel._select(*args)
120 | _select = _Channel._select
121 |
122 | def poison(*args):
123 | return _Channel.poison(*args)
124 | poison = _Channel.poison
125 |
126 |
127 |
--------------------------------------------------------------------------------
/csp/cchannels/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Generic Makefile for C modules, wrapped in Python by SWIG.
3 | #
4 | # Chanege the variable INTERFACE to your interface files and if you're
5 | # not using a sensible UNIX style platform then change the executables
6 | # and so on too.
7 | #
8 |
9 |
10 | INTERFACE=Channel.i
11 |
12 | PREFIX=/usr
13 | RM=rm
14 | SWIG=swig
15 | SWIGOPT=
16 | CC=gcc
17 | CFLAGS=-O3 -Wall -c
18 | LDSHARED=ld
19 | LDFLAGS=-shared
20 | INCLUDES=
21 | LIBS=
22 | SO=.so
23 |
24 | SRCS=$(wildcard *.c)
25 | ISRCS=$(INTERFACE:.i=_wrap.c)
26 | OBJS=${SRCS:.c=.o}
27 | IOBJS=$(ISRCS:.c=.o)
28 |
29 | TARGET=$(addprefix _, $(INTERFACE:.i=$(SO)))
30 |
31 | # Make sure these locate your Python installation
32 | PYTHON_INCLUDE=-I$(PREFIX)/include/python2.6
33 |
34 | # Clear out old suffices.
35 | .SUFFIXES:
36 |
37 | # List suffices that we are using.
38 | .SUFFIXES: .i .o .c
39 |
40 | .PHONY: clean
41 |
42 | all: $(SRCS)
43 | $(SWIG) -python $(SWIGOPT) $(INTERFACE)
44 | $(CC) -c $(CCSHARED) $(CFLAGS) $(ISRCS) $(SRCS) $(INCLUDE) $(PYTHON_INCLUDE)
45 | $(LDSHARED) $(LDFLAGS) $(OBJS) $(IOBJS) $(LIBS) -o $(TARGET)
46 | @echo Built all files and created $(TARGET)
47 |
48 | clean :
49 | -$(RM) -f *.pyc *.so *.o *_wrap.c *~
50 |
51 | depend : $(SRCS)
52 | makedepend $(INCLUDES) $^
53 |
54 | # DO NOT DELETE THIS LINE
55 |
--------------------------------------------------------------------------------
/csp/cchannels/tests/commstime.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """CSP Commstime benchmark.
3 |
4 | See F.R.M. Barnes (2006) Compiling CSP. In Proceedings of
5 | Communicating Process Architectures 2006.
6 |
7 | Code adapted from PyCSP by John Markus Bjorndalen, available:
8 | http://www.cs.uit.no/~johnm/code/PyCSP/
9 |
10 | PyCSP - Communicating Sequential Processes for Python. John Markus
11 | Bjorndalen, Brian Vinter, Otto Anshus. CPA 2007, Surrey, UK, July
12 | 8-11, 2007. IOS Press 2007, ISBN 978-1-58603-767-3, Concurrent
13 | Systems Engineering Series (ISSN 1383-7575).
14 | """
15 |
16 | from csp.csp import Par, process #, Channel
17 | from csp.builtins import Prefix, Delta2, Succ
18 |
19 | import sys
20 | sys.path.append('../')
21 | from CChannel import CChannel as Channel
22 | del sys
23 |
24 | import time
25 |
26 |
27 | @process
28 | def Consumer(cin):
29 | """Commstime consumer process
30 |
31 | readset = cin
32 | writeset =
33 | """
34 | N = 5000
35 | ts = time.time
36 | t1 = ts()
37 | cin.read()
38 | t1 = ts()
39 | for i in range(N):
40 | cin.read()
41 | t2 = ts()
42 | dt = t2-t1
43 | tchan = dt / (4 * N)
44 | print("DT = {0}\nTime per ch : {1}/(4*{2}) = {3} s = {4} us".format(dt, dt, N, tchan, tchan * 1000000))
45 | print("consumer done, poisoning channel")
46 | cin.poison()
47 |
48 | def CommsTimeBM():
49 | print('Creating channels now...')
50 | # Create channels
51 | a = Channel()
52 | b = Channel()
53 | c = Channel()
54 | d = Channel()
55 | print("Running commstime test")
56 | Par(Prefix(c, a, prefix_item=0), # Initiator
57 | Delta2(a, b, d), # Forwarding to two
58 | Succ(b, c), # Feeding back to prefix
59 | Consumer(d)).start() # Timing process
60 | print('Finished run...')
61 |
62 |
63 | if __name__ == '__main__':
64 | N_BM = 10
65 | for i in xrange(N_BM):
66 | print("----------- run {0}/{1} -------------".format(i+1, N_BM))
67 | CommsTimeBM()
68 | print("------- Commstime finished ---------")
69 |
--------------------------------------------------------------------------------
/csp/cchannels/tests/fulladder.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """Python CSP full adder.
4 |
5 | Based on code from PyCSP - Communicating Sequential Processes for
6 | Python. John Markus Bjorndalen, Brian Vinter, Otto Anshus. CPA 2007,
7 | Surrey, UK, July 8-11, 2007. IOS Press 2007, ISBN 978-1-58603-767-3,
8 | Concurrent Systems Engineering Series (ISSN 1383-7575).
9 |
10 | Copyright (C) Sarah Mount, 2009.
11 |
12 | This program is free software; you can redistribute it and/or
13 | modify it under the terms of the GNU General Public License
14 | as published by the Free Software Foundation; either version 2
15 | of the License, or (at your option) any later version.
16 |
17 | This program is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You should have rceeived a copy of the GNU General Public License
23 | along with this program; if not, write to the Free Software
24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 | """
26 |
27 | __author__ = 'Sarah Mount '
28 | __date__ = 'December 2008'
29 |
30 |
31 | from csp.csp import Par, process
32 |
33 | import sys
34 | sys.path.append('../')
35 | from CChannel import CChannel as Channel
36 | del sys
37 |
38 | from csp.builtins import *
39 |
40 |
41 | @process
42 | def Bool1(cout):
43 | """
44 | readset =
45 | writeset = cout
46 | """
47 | while True:
48 | cout.write(1)
49 | cout.write(1)
50 | cout.write(0)
51 | cout.write(0)
52 | return
53 |
54 | @process
55 | def Bool2(cout):
56 | """
57 | readset =
58 | writeset = cout
59 | """
60 | while True:
61 | cout.write(1)
62 | cout.write(0)
63 | cout.write(1)
64 | cout.write(0)
65 | return
66 |
67 | def fulladder(A_in, B_in, C_in, Sum_in, Carry_in):
68 | """Full adder implementation.
69 |
70 | Based on Bjorndalen, Vinter & Anshus (2007).
71 | """
72 | Aa = Channel()
73 | Ab = Channel()
74 | Ba = Channel()
75 | Bb = Channel()
76 | Ca = Channel()
77 | Cb = Channel()
78 | i1 = Channel()
79 | i1a = Channel()
80 | i1b = Channel()
81 | i2 = Channel()
82 | i3 = Channel()
83 |
84 | return Par(Delta2(A_in, Aa, Ab),
85 | Delta2(B_in, Ba, Bb),
86 | Delta2(C_in, Ca, Cb),
87 | Delta2(i1, i1a, i1b),
88 | Xor(Aa, Ba, i1),
89 | Xor(i1a, Ca, Sum_in),
90 | And(Ab, Bb, i2),
91 | And(i1b, Cb, i3),
92 | Or(i2, i3, Carry_in))
93 |
94 | if __name__ == '__main__':
95 | print('\nFull adder implemented in Python CSP\n')
96 | # Inputs to full adder
97 | A = Channel()
98 | B = Channel()
99 | Cin = Channel()
100 | # Outputs of full adder
101 | Carry = Channel()
102 | Sum = Channel()
103 | # Channels for printing to STDOUT
104 | PCarry = Channel()
105 | PSum = Channel()
106 | # Create and start adder
107 | adder = Par(Bool1(A),
108 | Bool2(B),
109 | Zeroes(Cin),
110 | fulladder(A, B, Cin, Sum, Carry),
111 | Sign(Carry, PCarry, 'Carry: '),
112 | Printer(PCarry),
113 | Sign(Sum, PSum, 'Sum: '),
114 | Printer(PSum))
115 | adder.start()
116 |
117 |
--------------------------------------------------------------------------------
/csp/cchannels/tests/patterns.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """Design pattern support for python-csp.
4 |
5 | Copyright (C) Sarah Mount, 2010.
6 |
7 | This program is free software; you can redistribute it and/or
8 | modify it under the terms of the GNU General Public License
9 | as published by the Free Software Foundation; either version 2
10 | of the License, or (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A ParTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have rceeived a copy of the GNU General Public License
18 | along with this program; if not, write to the Free Software
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 | """
21 |
22 |
23 | __author__ = 'Sarah Mount '
24 | __date__ = 'May 2010'
25 |
26 |
27 | from csp.csp import Par
28 |
29 | from CChannel import CChannel as Channel
30 |
31 | __all__ = ['TokenRing']
32 |
33 | class TokenRing(Par):
34 | def __init__(self, func, size, numtoks=1):
35 | self.chans = [Channel() for channel in xrange(size)]
36 | self.procs = [func(index=i,
37 | tokens=numtoks,
38 | numnodes=size,
39 | inchan=self.chans[i-1],
40 | outchan=self.chans[i]) for i in xrange(size)]
41 | super(TokenRing, self).__init__(*self.procs)
42 | return
43 |
44 |
--------------------------------------------------------------------------------
/csp/cchannels/tests/simple.py:
--------------------------------------------------------------------------------
1 | from csp.csp import Par, process
2 |
3 | import sys
4 | sys.path.append('../')
5 | from CChannel import CChannel as Channel
6 | del sys
7 |
8 |
9 | @process
10 | def out(cout):
11 | i = 0
12 | while True:
13 | print ( "PYTHON: About to write " + str ( i ) + "\n" )
14 | cout.write(i)
15 | print ( "PYTHON: Have written " + str ( i ) + "\n" )
16 | i = i +1
17 |
18 |
19 | @process
20 | def inn(cin):
21 | while True:
22 | print ( "PYTHON: About to read \n" )
23 | a = cin.read()
24 | print ( "PYTHON: Read "+ str ( a ) + "\n" )
25 |
26 |
27 | if __name__ == '__main__':
28 |
29 | c = Channel()
30 | p = Par(out(c),inn(c))
31 | p.start()
32 |
--------------------------------------------------------------------------------
/csp/cchannels/tests/tokenring.py:
--------------------------------------------------------------------------------
1 | #! /bin/env python2.6
2 |
3 | """
4 | Benchmark based on variable sized ring buffer.
5 | See also PyCSP papers in CPA2009 proceedings.
6 |
7 | Usage: tokenring-processes.py [options]
8 |
9 | Options:
10 | -h, --help show this help message and exit
11 | -t TOKENS, --tokens=TOKENS
12 | Number of tokens in token ring
13 | -n NODES, --nodes=NODES
14 | Number of nodes in token ring
15 | -x, --experiment Experimental mode. Run 10 token rings with nodes 2^1
16 | to 2^10 and print results
17 |
18 | Copyright (C) Sarah Mount, 2009.
19 |
20 | This program is free software; you can redistribute it and/or
21 | modify it under the terms of the GNU General Public License
22 | as published by the Free Software Foundation; either version 2
23 | of the License, or (at your option) any later version.
24 |
25 | This program is distributed in the hope that it will be useful,
26 | but WITHOUT ANY WARRANTY; without even the implied warranty of
27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 | GNU General Public License for more details.
29 |
30 | You should have rceeived a copy of the GNU General Public License
31 | along with this program; if not, write to the Free Software
32 |
33 | """
34 |
35 | __author__ = 'Sarah Mount '
36 | __date__ = 'November 2009'
37 |
38 | from csp.csp import process, Par
39 | from patterns import TokenRing
40 |
41 | import sys
42 | sys.path.append('../')
43 | from CChannel import CChannel as Channel
44 | del sys
45 |
46 | import time
47 |
48 | TRIALS = 10000
49 |
50 |
51 | @process
52 | def ringproc(index=0, numnodes=64, tokens=1, inchan=None, outchan=None):
53 | """
54 | readset = inchan
55 | writeset = outchan
56 | """
57 | if tokens == 1 and index == 0:
58 | token = 1
59 | outchan.write(token)
60 | for i in xrange(TRIALS):
61 | outchan.write(inchan.read())
62 | # Avoid deadlock.
63 | if index == 1:
64 | inchan.read()
65 |
66 |
67 | if __name__ == '__main__':
68 | from optparse import OptionParser
69 |
70 | parser = OptionParser()
71 |
72 | parser.add_option('-t', '--tokens', dest='tokens',
73 | action='store', type="int",
74 | default=1,
75 | help='Number of tokens in token ring')
76 | parser.add_option('-n', '--nodes', dest='nodes',
77 | action='store', type="int",
78 | default=64,
79 | help='Number of nodes in token ring')
80 | parser.add_option('-x', '--experiment', dest='exp',
81 | action='store_true', default=False,
82 | help=('Experimental mode. Run 10 token rings with nodes '
83 | + '2^1 to 2^10 and print results'))
84 |
85 | (options, args) = parser.parse_args()
86 |
87 | if options.exp:
88 | print('All times measured in microseconds.')
89 | for size in xrange(2, 50):
90 | try:
91 | print('Token ring with {0} nodes.'.format(2 ** size))
92 | starttime = time.time()
93 | TokenRing(ringproc, 2 ** size, numtoks=options.tokens).start()
94 | elapsed = time.time() - starttime
95 | mu = elapsed * 1000000 / float((TRIALS * (2 ** size)))
96 | print('{0}ms'.format(mu))
97 | except:
98 | continue
99 | else:
100 | TokenRing(ringproc, options.nodes, numtoks=options.tokens).start()
101 |
--------------------------------------------------------------------------------
/csp/csp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | If you want to use the python-csp library then this is the file to
5 | import. It attempts to match the best possible implementation of CSP
6 | for your platform.
7 |
8 | If you wish to choose to use the multiprocess (multicore) or threaded
9 | version of the libraries explicitly then set an environment variable
10 | in your opertaing system called "CSP". This should be either set to
11 | "PROCESSES" or "THREADS" depending on what you want to use.
12 |
13 |
14 | Copyright (C) Sarah Mount, 2010.
15 |
16 | This program is free software; you can redistribute it and/or
17 | modify it under the terms of the GNU General Public License
18 | as published by the Free Software Foundation; either version 2
19 | of the License, or (at your option) any later version.
20 |
21 | This program is distributed in the hope that it will be useful,
22 | but WITHOUT ANY WARRANTY; without even the implied warranty of
23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 | GNU General Public License for more details.
25 |
26 | You should have received a copy of the GNU General Public License
27 | along with this program; if not, write to the Free Software
28 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
29 | """
30 |
31 | from __future__ import absolute_import
32 |
33 | from contextlib import contextmanager
34 |
35 | import os
36 | import sys
37 |
38 |
39 | ### Names exported by this module
40 | __all__ = ['set_debug', 'CSPProcess', 'CSPServer', 'Alt',
41 | 'Par', 'Seq', 'Guard', 'Channel', 'FileChannel',
42 | 'process', 'forever', 'Skip', 'CSP_IMPLEMENTATION']
43 |
44 |
45 | __author__ = 'Sarah Mount '
46 | __date__ = 'July 2010'
47 |
48 |
49 | # FIXME: Simplify this logic. See the thread on "Importing different
50 | # implementations of the library" on the mailing list.
51 |
52 | # If multiprocessing is not available then import threads.
53 | major, minor = sys.version_info[:2]
54 | if (major, minor) < (2, 6):
55 | try:
56 | from .os_thread import *
57 | except:
58 | from .os_process import *
59 |
60 | # If multiprocessing is likely to be available then let the user
61 | # choose which version of the implementation they wish to use.
62 | elif 'CSP' in os.environ:
63 | if os.environ['CSP'].upper() == 'THREADS':
64 | from .os_thread import *
65 | else:
66 | from .os_process import *
67 |
68 | # If no useful information is available then try to import the
69 | # multiprocessing version of the code else catch the resulting
70 | # exception and use the threaded version.
71 | else:
72 | try:
73 | from .os_process import *
74 | except:
75 | from .os_thread import *
76 |
77 |
78 |
79 | class CSP(object):
80 | """Context manager to execute Python functions sequentially or in
81 | parallel, similarly to OCCAM syntax:
82 |
83 | csp = CSP()
84 | with csp.seq:
85 | csp.process(myfunc1, arg1, arg2)
86 | with csp.par:
87 | csp.process(myfunc2, arg1, arg2)
88 | csp.process(myfunc3, arg1, arg2)
89 | csp.start()
90 | # myfunc3 and myfunc4 will be executed in parallel.
91 | # myfunc1 and myfunc2 will be executed sequentially,
92 | # and myfunc3 and myfunc4 will be executed after
93 | # myfunc2 has returned.
94 | """
95 |
96 | def __init__(self):
97 | self.processes = []
98 |
99 | @contextmanager
100 | def par(self):
101 | """Context manager to execute functions in parallel.
102 |
103 | csp = CSP()
104 | with csp.seq:
105 | csp.process(myfunc1, arg1, arg2)
106 | csp.process(myfunc2, arg1, arg2)
107 | csp.start()
108 | # myfunc1 and myfunc2 will be executed in parallel.
109 | """
110 | self.processes.append([])
111 | yield
112 | proc_list = self.processes.pop()
113 | par = Par(*proc_list)
114 | if len(self.processes) > 0:
115 | self.processes[-1].append(par)
116 | else:
117 | self.processes.append(par)
118 | return
119 |
120 | @contextmanager
121 | def seq(self):
122 | """Context manager to execute functions in sequence.
123 |
124 | csp = CSP()
125 | with csp.seq:
126 | csp.process(myfunc1, arg1, arg2)
127 | csp.process(myfunc2, arg1, arg2)
128 | csp.start()
129 | # myfunc1 and myfunc2 will be executed sequentially.
130 | """
131 | self.processes.append([])
132 | yield
133 | proc_list = self.processes.pop()
134 | seq = Seq(*proc_list)
135 | if len(self.processes) > 0:
136 | self.processes[-1].append(seq)
137 | else:
138 | self.processes.append(seq)
139 | return
140 |
141 | def process(self, func, *args, **kwargs):
142 | """Add a process to the current list of proceses.
143 |
144 | Likely, this will be called from inside a context manager, e.g.:
145 |
146 | csp = CSP()
147 | with csp.par:
148 | csp.process(myfunc1, arg1, arg2)
149 | csp.process(myfunc2, arg1, arg2)
150 | csp.start()
151 | """
152 | self.processes[-1].append(CSPProcess(func, *args, **kwargs))
153 | return
154 |
155 | def start(self):
156 | """Start all processes in self.processes (in parallel) and run
157 | to completion.
158 | """
159 | if len(self.processes) == 0:
160 | return
161 | elif len(self.processes) == 1:
162 | self.processes[0].start()
163 | else:
164 | Par(*self.processes).start()
165 | return
166 |
--------------------------------------------------------------------------------
/csp/dsp.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python
2 |
3 | """
4 | Digital signal processing for python-csp.
5 |
6 | Copyright (C) Sarah Mount, 2009.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | from __future__ import absolute_import
23 |
24 | from .csp import *
25 |
26 | import math
27 |
28 | # TODO: Use numpy for more sophisticated processes.
29 |
30 | ACCEL_DUE_TO_GRAVITY = 9.80665
31 |
32 |
33 | @forever
34 | def Zip(outchan, inchannels):
35 | """Take data from a number of input channels, and write that
36 | data as a single list to L{outchan}.
37 | """
38 | while True:
39 | outchan.write([chan.read() for chan in inchannels])
40 | yield
41 |
42 |
43 | @forever
44 | def Unzip(inchan, outchans):
45 | """Continuously read tuples of data from a single input channel and send
46 | each datum out down its own output channel.
47 | """
48 | while True:
49 | data = inchan.read()
50 | for i in range(data):
51 | outchans[i].write(data[i])
52 | yield
53 |
54 |
55 | @forever
56 | def Sin(inchan, outchan):
57 | while True:
58 | outchan.write(math.sin(inchan.read()))
59 | yield
60 |
61 |
62 | @forever
63 | def Cos(inchan, outchan):
64 | while True:
65 | outchan.write(math.cos(inchan.read()))
66 | yield
67 |
68 |
69 | @forever
70 | def Tan(inchan, outchan):
71 | while True:
72 | outchan.write(math.tan(inchan.read()))
73 | yield
74 |
75 |
76 | @forever
77 | def GenerateFloats(outchan):
78 | counter = 0
79 | increment = 0.1
80 | while True:
81 | outchan.write(counter * increment)
82 | counter += 1
83 | yield
84 |
85 |
86 | @forever
87 | def Magnitude(inchan, outchan):
88 | while True:
89 | acceldata = inchan.read()
90 | mag = 0.0
91 | for axis in acceldata: mag += axis ** 2
92 | outchan.write(math.sqrt(mag))
93 | yield
94 |
95 |
96 | @forever
97 | def Difference(inchan, outchan, window=1):
98 | cache = 0.0
99 | while True:
100 | acceldata = inchan.read()
101 | try:
102 | outchan.write(acceldata - cache)
103 | cache = acceldata
104 | except IndexError:
105 | pass
106 | yield
107 |
108 |
109 | @forever
110 | def Square(inchan, outchan):
111 | while True:
112 | data = inchan.read()
113 | outchan.write(data ** 2)
114 | yield
115 |
116 |
117 | @forever
118 | def Normalise(inchan, outchan, start=0.0, end=100.0):
119 | scale = end - start
120 | while True:
121 | outchan.write(inchan.read() / scale)
122 | yield
123 |
124 |
125 | @forever
126 | def Threshold(thresh, inchan, outchan):
127 | while True:
128 | mag = inchan.read()
129 | if mag >= thresh:
130 | outchan.write(mag)
131 | yield
132 |
133 |
--------------------------------------------------------------------------------
/csp/guards.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Builtin guard types. For builtin processes see csp.builtins.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | from __future__ import absolute_import
23 |
24 | import os
25 | import multiprocessing
26 | import threading
27 | import time
28 |
29 | from .csp import *
30 |
31 |
32 | __author__ = 'Sarah Mount '
33 | __date__ = 'May 2010'
34 |
35 |
36 | ### Names exported by this module
37 | __all__ = ['Timer', 'Barrier']
38 |
39 | class Timer(Guard):
40 | """Guard which only commits to synchronisation when a timer has expired.
41 |
42 | Timer objects are a type of CSP guard, like Channel types and Skip
43 | guards. Timer objects allow code to wait for a specific period of
44 | time before synchronising on a timer event. This can be done in a
45 | number of ways: either by sleeping for a period of time (similar
46 | to time.sleep in the standard library), or by setting the timer to
47 | become selectable (by an Alt object) after a specific period of
48 | time. For example:
49 |
50 | >>> timer = Timer()
51 | >>> timer.sleep(5) # sleep for 5 seconds
52 | >>>
53 | >>> alt = Alt(timer)
54 | >>> timer.set_alarm(3) # become selectable 3 seconds from now
55 | >>> alt.select() # will wait 3 seconds
56 | >>>
57 | """
58 |
59 | def __init__(self):
60 | super(Timer, self).__init__()
61 | self.now = time.time()
62 | self.name = 'Timer guard created at:' + str(self.now)
63 | self.alarm = None
64 |
65 | def set_alarm(self, timeout):
66 | self.now = time.time()
67 | self.alarm = self.now + timeout
68 |
69 | def is_selectable(self):
70 | self.now = time.time()
71 | if self.alarm is None:
72 | return True
73 | elif self.now < self.alarm:
74 | return False
75 | return True
76 |
77 | def read(self):
78 | """Return current time.
79 | """
80 | self.now = time.time()
81 | return self.now
82 |
83 | def sleep(self, timeout):
84 | """Put this process to sleep for a number of seconds.
85 | """
86 | time.sleep(timeout)
87 |
88 | def enable(self):
89 | pass
90 |
91 | def disable(self):
92 | pass
93 |
94 | def select(self):
95 | pass
96 |
97 |
98 | class AbstractBarrier(object):
99 |
100 | def __init__(self, participants=0):
101 | self.participants = participants
102 | self.not_ready = participants
103 | self.lock = None # MUST be overridden in subclass
104 | self.reset(participants)
105 |
106 | def reset(self, participants):
107 | assert participants >= 0
108 | with self.lock:
109 | self.participants = participants
110 | self.not_ready = participants
111 |
112 | def enrol(self):
113 | with self.lock:
114 | self.participants += 1
115 | self.not_ready += 1
116 |
117 | def retire(self):
118 | with self.lock:
119 | self.participants -= 1
120 | self.not_ready -= 1
121 | if self.not_ready == 0:
122 | self.not_ready = self.participants
123 | self.lock.notifyAll()
124 | assert self.not_ready >= 0
125 |
126 | def synchronise(self):
127 | with self.lock:
128 | self.not_ready -= 1
129 | if self.not_ready > 0:
130 | self.lock.wait()
131 | else:
132 | self.not_ready = self.participants
133 | self.lock.notifyAll()
134 |
135 | def synchronise_withN(self, n):
136 | """Only syncrhonise when N participants are enrolled.
137 | """
138 | with self.lock:
139 | if self.participants != n:
140 | self.lock.wait()
141 | self.not_ready -= 1
142 | if self.not_ready > 0:
143 | self.lock.wait()
144 | else:
145 | self.not_ready = self.participants
146 | self.lock.notifyAll()
147 |
148 |
149 | # TODO: Move these two classes to the modules corresponding to
150 | # their CSP process implementation (i. e. os_process/os_thread).
151 |
152 | class BarrierThreading(AbstractBarrier):
153 |
154 | def __init__(self):
155 | super(BarrierThreading, self).__init__()
156 | self.lock = threading.Condition()
157 |
158 |
159 | class BarrierProcessing(AbstractBarrier):
160 |
161 | def __init__(self):
162 | super(BarrierProcessing, self).__init__()
163 | self.lock = multiprocessing.Condition()
164 |
165 |
166 | # Use os processes unless requested otherwise.
167 | if CSP_IMPLEMENTATION == 'os_thread':
168 | Barrier = BarrierThreading
169 | else:
170 | Barrier = BarrierProcessing
171 |
172 | #Barrier.__doc__ = """
173 | #
174 | #"""
175 |
--------------------------------------------------------------------------------
/csp/lint/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/csp/lint/__init__.py
--------------------------------------------------------------------------------
/csp/lint/lint.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Combined linting for python-csp.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | import compiler
23 | import csp.lint.channels
24 | import csp.lint.processes
25 |
26 | import exstatic.cspwarnings
27 |
28 |
29 | __all__ = ['run']
30 |
31 |
32 | checkers = [csp.lint.channels.ChannelChecker,
33 | csp.lint.processes.ProcessChecker]
34 |
35 |
36 | def run(filename, excluded=[]):
37 | exstatic.cspwarnings.reset_errors()
38 | for checker in checkers:
39 | lint = checker(filename)
40 | compiler.walk(compiler.parseFile(filename),
41 | lint,
42 | walker=lint,
43 | verbose=5)
44 | exstatic.cspwarnings.print_errors(excluded=excluded)
45 | return
46 |
47 | if __name__ == '__main__':
48 | import sys
49 | if sys.argv > 1:
50 | run(sys.argv[1])
51 | sys.exit()
52 |
--------------------------------------------------------------------------------
/csp/lint/processes.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Check for errors in process definitions.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | import compiler
23 | import compiler.ast as ast
24 | import compiler.visitor as visitor
25 |
26 | import exstatic.cspwarnings
27 |
28 |
29 | __author__ = 'Sarah Mount '
30 | __date__ = 'May 2010'
31 |
32 |
33 | __all__ = ['ProcessChecker']
34 |
35 | class ProcessChecker(visitor.ASTVisitor):
36 | """Check that documented readsets and writesets are correct
37 | w.r.t. code.
38 | """
39 |
40 | def __init__(self, filename):
41 | visitor.ASTVisitor.__init__(self)
42 | self.filename = filename
43 | self.current_process = ''
44 | self.current_process_lineno = 0
45 | return
46 |
47 |
48 | def is_process(self, decorators):
49 | """Determine whether or not the current function is a CSP
50 | process.
51 | """
52 | for decorator in decorators:
53 | if (decorator.name == 'process' or decorator.name == 'forever'):
54 | return True
55 | return False
56 |
57 |
58 | def visitFunction(self, node):
59 | """Visit function definition.
60 | """
61 |
62 | # If this function definition is not a CSP process, ignore it.
63 | if (node.decorators is None or
64 | self.is_process(node.decorators) is None):
65 | return
66 |
67 | # Store useful information about this process.
68 | self.current_process = node.name
69 | self.current_process_lineno = node.lineno
70 |
71 | # 'I001':'Function is a CSP process or server process',
72 | exstatic.cspwarnings.create_error(self.filename,
73 | self.current_process_lineno,
74 | self.current_process,
75 | 'I001')
76 |
77 | # 'W004':'@process or @forever applied to method (rather than function)'
78 | if 'self' in node.argnames:
79 | exstatic.cspwarnings.create_error(self.filename,
80 | self.current_process_lineno,
81 | self.current_process,
82 | 'W004')
83 |
84 | return
85 |
86 |
87 | if __name__ == '__main__':
88 | import sys
89 |
90 | lint = ProcessChecker(sys.argv[1])
91 | compiler.walk(compiler.parseFile(sys.argv[1]),
92 | lint,
93 | walker=lint,
94 | verbose=5)
95 |
96 | exstatic.cspwarnings.print_errors(excluded=[])
97 |
--------------------------------------------------------------------------------
/csp/patterns.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """Design pattern support for python-csp.
4 |
5 | Copyright (C) Sarah Mount, 2010.
6 |
7 | This program is free software; you can redistribute it and/or
8 | modify it under the terms of the GNU General Public License
9 | as published by the Free Software Foundation; either version 2
10 | of the License, or (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A ParTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have rceeived a copy of the GNU General Public License
18 | along with this program; if not, write to the Free Software
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 | """
21 |
22 |
23 | from __future__ import absolute_import
24 |
25 | from .csp import *
26 |
27 |
28 | __author__ = 'Sarah Mount '
29 | __date__ = 'May 2010'
30 |
31 |
32 | __all__ = ['TokenRing']
33 |
34 |
35 | class TokenRing(Par):
36 |
37 | def __init__(self, func, size, numtoks=1):
38 | self.chans = [Channel() for channel in range(size)]
39 | self.procs = [func(index=i,
40 | tokens=numtoks,
41 | numnodes=size,
42 | inchan=self.chans[i-1],
43 | outchan=self.chans[i]) for i in range(size)]
44 | super(TokenRing, self).__init__(*self.procs)
45 |
46 |
--------------------------------------------------------------------------------
/csp/tracer/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/csp/tracer/__init__.py
--------------------------------------------------------------------------------
/csp/tracer/cspmodel.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Simple representation of CSP models, with graphviz and FDR2 output.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | __author__ = 'Sarah Mount '
23 | __date__ = '2010-05-16'
24 |
25 |
26 | class CSPModel(object):
27 |
28 | def __init__(self):
29 | return
30 |
31 | def fdr(self):
32 | """Generate a variant of this CSP model to a text file.
33 | Should be suitable for using as an input to the FDR2 tool.
34 |
35 | MUST be overridden in subclasses.
36 | """
37 | raise Exception('fdr() MUST be overridden in subclasses.')
38 |
39 | def dot(self):
40 | """Generate a variant of this CSP model to a text file.
41 | Should be suitable for using as an input to the graphiz toolset.
42 |
43 | MUST be overridden in subclasses.
44 | """
45 | raise Exception('fdr() MUST be overridden in subclasses.')
46 |
47 |
48 |
49 | class Process(CSPModel):
50 |
51 | def __init__(self, name):
52 | CSPModel.__init__(self)
53 | self.name = name
54 |
55 | def fdr(self):
56 | # WRONG, this should be a definition
57 | return self.name.upper()
58 |
59 |
60 | class Par(CSPModel):
61 |
62 | def __init__(self, procs):
63 | CSPModel.__init__(self)
64 | self.procs = procs
65 |
66 | def fdr(self):
67 | if len(self.procs) == 0:
68 | return ''
69 | fdr_string = self.procs[0].fdr()
70 | for proc in self.procs[1:]:
71 | fdr_string += ' ||| ' + proc
72 | return fdr_string
73 |
74 |
75 | class Seq(CSPModel):
76 |
77 | def __init__(self, procs):
78 | CSPModel.__init__(self)
79 | self.procs = procs
80 | return
81 |
82 | def fdr(self):
83 | if len(self.procs) == 0:
84 | return ''
85 | fdr_string = self.procs[0].fdr()
86 | for proc in self.procs[1:]:
87 | fdr_string += ' ; ' + proc
88 | return fdr_string
89 |
90 |
91 | class Channel(CSPModel):
92 |
93 | def __init__(self, name):
94 | CSPModel.__init__(self)
95 | self.name = name
96 | return
97 |
98 | def fdr(self):
99 | return 'channel ' + self.name + '\n'
100 |
101 |
102 | # def write_dotfile(filename='procgraph.dot'):
103 | # global nodes
104 | # global arcs
105 | # dot = "graph pythoncsp {\n node [shape=ellipse];"
106 | # for proc in nodes:
107 | # dot += " " + str(proc) + ";"
108 | # dot += "\n"
109 | # for channel in arcs:
110 | # for i in xrange(len(arcs[channel])):
111 | # for j in xrange(i+1, len(arcs[channel])):
112 | # dot += (str(arcs[channel][i]) + " -- " +
113 | # str(arcs[channel][j]) +
114 | # " [ label=" + str(channel) + " ];\n")
115 | # dot += ' label = "\\n\\nCSP Process Relationships\\n";\n'
116 | # dot += " fontsize=20;\n}"
117 | # fh = open(filename)
118 | # fh.write(dot)
119 | # fh.close()
120 | # return
121 |
122 |
123 | # def write_png(infile='procgraph.dot', outfile='procgraph.png'):
124 | # os.system('neato -v -Goverlap=-1 -Gsplines=true -Gsep=.1 -Gstart=-1000 Gepsilon=.0000000001 -Tpng ' + infile + ' -o' + outfile)
125 |
126 |
127 | if __name__ == '__main__':
128 | print ( 'WRITE SOME TESTS' )
129 |
130 |
--------------------------------------------------------------------------------
/docs/doctrees/builtins.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/builtins.doctree
--------------------------------------------------------------------------------
/docs/doctrees/csp.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/csp.doctree
--------------------------------------------------------------------------------
/docs/doctrees/environment.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/environment.pickle
--------------------------------------------------------------------------------
/docs/doctrees/guards.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/guards.doctree
--------------------------------------------------------------------------------
/docs/doctrees/index.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/index.doctree
--------------------------------------------------------------------------------
/docs/doctrees/mandelbrot.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/mandelbrot.doctree
--------------------------------------------------------------------------------
/docs/doctrees/patterns.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/patterns.doctree
--------------------------------------------------------------------------------
/docs/doctrees/tracer.doctree:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/doctrees/tracer.doctree
--------------------------------------------------------------------------------
/docs/html/.buildinfo:
--------------------------------------------------------------------------------
1 | # Sphinx build info version 1
2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3 | config: a8271a5c91c46cfcc096a0b82e63654b
4 | tags: fbb0d17656682115ca4d033fb2f83ba1
5 |
--------------------------------------------------------------------------------
/docs/html/_sources/builtins.txt:
--------------------------------------------------------------------------------
1 | Pre-built proceses
2 | ==================
3 |
4 | .. automodule:: csp.builtins
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/docs/html/_sources/csp.txt:
--------------------------------------------------------------------------------
1 | Core CSP library.
2 | =================
3 |
4 | .. automodule:: csp.csp
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/docs/html/_sources/guards.txt:
--------------------------------------------------------------------------------
1 | Prebuilt synchronisation primitives.
2 | ====================================
3 |
4 | .. automodule:: csp.guards
5 | :members:
6 |
7 | ..
8 |
9 |
10 | * :ref:`genindex`
11 | * :ref:`modindex`
12 | * :ref:`search`
13 |
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/index.txt:
--------------------------------------------------------------------------------
1 | .. python-csp documentation master file, created by
2 | sphinx-quickstart on Sat Apr 10 00:03:15 2010.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to python-csp's documentation!
7 | ======================================
8 |
9 | Contents:
10 |
11 | .. toctree::
12 | :maxdepth: 2
13 |
14 | csp.rst
15 | builtins.rst
16 | guards.rst
17 | patterns.rst
18 | tracer.rst
19 | mandelbrot.rst
20 |
21 |
22 | ..
23 |
24 | Indices and tables
25 | ==================
26 |
27 | * :ref:`genindex`
28 | * :ref:`modindex`
29 | * :ref:`search`
30 |
31 |
--------------------------------------------------------------------------------
/docs/html/_sources/mandelbrot.txt:
--------------------------------------------------------------------------------
1 | Mandelbrot example
2 | ==================
3 |
4 | .. automodule:: mandelbrot
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/docs/html/_sources/patterns.txt:
--------------------------------------------------------------------------------
1 | Design patterns for automatically wiring process graphs
2 | =======================================================
3 |
4 | .. automodule:: csp.patterns
5 | :members:
6 |
7 | ..
8 |
9 |
10 | * :ref:`genindex`
11 | * :ref:`modindex`
12 | * :ref:`search`
13 |
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/tracer.txt:
--------------------------------------------------------------------------------
1 | Debugging with the tracer module
2 | ================================
3 |
4 | .. automodule:: csp.tracer
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/docs/html/_static/default.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Sphinx stylesheet -- default theme
3 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 | */
5 |
6 | @import url("basic.css");
7 |
8 | /* -- page layout ----------------------------------------------------------- */
9 |
10 | body {
11 | font-family: sans-serif;
12 | font-size: 100%;
13 | background-color: #11303d;
14 | color: #000;
15 | margin: 0;
16 | padding: 0;
17 | }
18 |
19 | div.document {
20 | background-color: #1c4e63;
21 | }
22 |
23 | div.documentwrapper {
24 | float: left;
25 | width: 100%;
26 | }
27 |
28 | div.bodywrapper {
29 | margin: 0 0 0 230px;
30 | }
31 |
32 | div.body {
33 | background-color: #ffffff;
34 | color: #000000;
35 | padding: 0 20px 30px 20px;
36 | }
37 |
38 | div.footer {
39 | color: #ffffff;
40 | width: 100%;
41 | padding: 9px 0 9px 0;
42 | text-align: center;
43 | font-size: 75%;
44 | }
45 |
46 | div.footer a {
47 | color: #ffffff;
48 | text-decoration: underline;
49 | }
50 |
51 | div.related {
52 | background-color: #133f52;
53 | line-height: 30px;
54 | color: #ffffff;
55 | }
56 |
57 | div.related a {
58 | color: #ffffff;
59 | }
60 |
61 | div.sphinxsidebar {
62 | }
63 |
64 | div.sphinxsidebar h3 {
65 | font-family: 'Trebuchet MS', sans-serif;
66 | color: #ffffff;
67 | font-size: 1.4em;
68 | font-weight: normal;
69 | margin: 0;
70 | padding: 0;
71 | }
72 |
73 | div.sphinxsidebar h3 a {
74 | color: #ffffff;
75 | }
76 |
77 | div.sphinxsidebar h4 {
78 | font-family: 'Trebuchet MS', sans-serif;
79 | color: #ffffff;
80 | font-size: 1.3em;
81 | font-weight: normal;
82 | margin: 5px 0 0 0;
83 | padding: 0;
84 | }
85 |
86 | div.sphinxsidebar p {
87 | color: #ffffff;
88 | }
89 |
90 | div.sphinxsidebar p.topless {
91 | margin: 5px 10px 10px 10px;
92 | }
93 |
94 | div.sphinxsidebar ul {
95 | margin: 10px;
96 | padding: 0;
97 | color: #ffffff;
98 | }
99 |
100 | div.sphinxsidebar a {
101 | color: #98dbcc;
102 | }
103 |
104 | div.sphinxsidebar input {
105 | border: 1px solid #98dbcc;
106 | font-family: sans-serif;
107 | font-size: 1em;
108 | }
109 |
110 | /* -- body styles ----------------------------------------------------------- */
111 |
112 | a {
113 | color: #355f7c;
114 | text-decoration: none;
115 | }
116 |
117 | a:hover {
118 | text-decoration: underline;
119 | }
120 |
121 | div.body p, div.body dd, div.body li {
122 | text-align: justify;
123 | line-height: 130%;
124 | }
125 |
126 | div.body h1,
127 | div.body h2,
128 | div.body h3,
129 | div.body h4,
130 | div.body h5,
131 | div.body h6 {
132 | font-family: 'Trebuchet MS', sans-serif;
133 | background-color: #f2f2f2;
134 | font-weight: normal;
135 | color: #20435c;
136 | border-bottom: 1px solid #ccc;
137 | margin: 20px -20px 10px -20px;
138 | padding: 3px 0 3px 10px;
139 | }
140 |
141 | div.body h1 { margin-top: 0; font-size: 200%; }
142 | div.body h2 { font-size: 160%; }
143 | div.body h3 { font-size: 140%; }
144 | div.body h4 { font-size: 120%; }
145 | div.body h5 { font-size: 110%; }
146 | div.body h6 { font-size: 100%; }
147 |
148 | a.headerlink {
149 | color: #c60f0f;
150 | font-size: 0.8em;
151 | padding: 0 4px 0 4px;
152 | text-decoration: none;
153 | }
154 |
155 | a.headerlink:hover {
156 | background-color: #c60f0f;
157 | color: white;
158 | }
159 |
160 | div.body p, div.body dd, div.body li {
161 | text-align: justify;
162 | line-height: 130%;
163 | }
164 |
165 | div.admonition p.admonition-title + p {
166 | display: inline;
167 | }
168 |
169 | div.note {
170 | background-color: #eee;
171 | border: 1px solid #ccc;
172 | }
173 |
174 | div.seealso {
175 | background-color: #ffc;
176 | border: 1px solid #ff6;
177 | }
178 |
179 | div.topic {
180 | background-color: #eee;
181 | }
182 |
183 | div.warning {
184 | background-color: #ffe4e4;
185 | border: 1px solid #f66;
186 | }
187 |
188 | p.admonition-title {
189 | display: inline;
190 | }
191 |
192 | p.admonition-title:after {
193 | content: ":";
194 | }
195 |
196 | pre {
197 | padding: 5px;
198 | background-color: #eeffcc;
199 | color: #333333;
200 | line-height: 120%;
201 | border: 1px solid #ac9;
202 | border-left: none;
203 | border-right: none;
204 | }
205 |
206 | tt {
207 | background-color: #ecf0f3;
208 | padding: 0 1px 0 1px;
209 | font-size: 0.95em;
210 | }
211 |
212 | .warning tt {
213 | background: #efc2c2;
214 | }
215 |
216 | .note tt {
217 | background: #d6d6d6;
218 | }
--------------------------------------------------------------------------------
/docs/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/html/_static/file.png
--------------------------------------------------------------------------------
/docs/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/html/_static/pygments.css:
--------------------------------------------------------------------------------
1 | .hll { background-color: #ffffcc }
2 | .c { color: #408090; font-style: italic } /* Comment */
3 | .err { border: 1px solid #FF0000 } /* Error */
4 | .k { color: #007020; font-weight: bold } /* Keyword */
5 | .o { color: #666666 } /* Operator */
6 | .cm { color: #408090; font-style: italic } /* Comment.Multiline */
7 | .cp { color: #007020 } /* Comment.Preproc */
8 | .c1 { color: #408090; font-style: italic } /* Comment.Single */
9 | .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
10 | .gd { color: #A00000 } /* Generic.Deleted */
11 | .ge { font-style: italic } /* Generic.Emph */
12 | .gr { color: #FF0000 } /* Generic.Error */
13 | .gh { color: #000080; font-weight: bold } /* Generic.Heading */
14 | .gi { color: #00A000 } /* Generic.Inserted */
15 | .go { color: #303030 } /* Generic.Output */
16 | .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
17 | .gs { font-weight: bold } /* Generic.Strong */
18 | .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
19 | .gt { color: #0040D0 } /* Generic.Traceback */
20 | .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
21 | .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
22 | .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
23 | .kp { color: #007020 } /* Keyword.Pseudo */
24 | .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
25 | .kt { color: #902000 } /* Keyword.Type */
26 | .m { color: #208050 } /* Literal.Number */
27 | .s { color: #4070a0 } /* Literal.String */
28 | .na { color: #4070a0 } /* Name.Attribute */
29 | .nb { color: #007020 } /* Name.Builtin */
30 | .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
31 | .no { color: #60add5 } /* Name.Constant */
32 | .nd { color: #555555; font-weight: bold } /* Name.Decorator */
33 | .ni { color: #d55537; font-weight: bold } /* Name.Entity */
34 | .ne { color: #007020 } /* Name.Exception */
35 | .nf { color: #06287e } /* Name.Function */
36 | .nl { color: #002070; font-weight: bold } /* Name.Label */
37 | .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
38 | .nt { color: #062873; font-weight: bold } /* Name.Tag */
39 | .nv { color: #bb60d5 } /* Name.Variable */
40 | .ow { color: #007020; font-weight: bold } /* Operator.Word */
41 | .w { color: #bbbbbb } /* Text.Whitespace */
42 | .mf { color: #208050 } /* Literal.Number.Float */
43 | .mh { color: #208050 } /* Literal.Number.Hex */
44 | .mi { color: #208050 } /* Literal.Number.Integer */
45 | .mo { color: #208050 } /* Literal.Number.Oct */
46 | .sb { color: #4070a0 } /* Literal.String.Backtick */
47 | .sc { color: #4070a0 } /* Literal.String.Char */
48 | .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
49 | .s2 { color: #4070a0 } /* Literal.String.Double */
50 | .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
51 | .sh { color: #4070a0 } /* Literal.String.Heredoc */
52 | .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
53 | .sx { color: #c65d09 } /* Literal.String.Other */
54 | .sr { color: #235388 } /* Literal.String.Regex */
55 | .s1 { color: #4070a0 } /* Literal.String.Single */
56 | .ss { color: #517918 } /* Literal.String.Symbol */
57 | .bp { color: #007020 } /* Name.Builtin.Pseudo */
58 | .vc { color: #bb60d5 } /* Name.Variable.Class */
59 | .vg { color: #bb60d5 } /* Name.Variable.Global */
60 | .vi { color: #bb60d5 } /* Name.Variable.Instance */
61 | .il { color: #208050 } /* Literal.Number.Integer.Long */
--------------------------------------------------------------------------------
/docs/html/_static/pythoncsp-docs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/docs/html/_static/pythoncsp-docs.png
--------------------------------------------------------------------------------
/docs/html/modindex.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | Global Module Index — python-csp v0.1 documentation
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
Global Module Index
48 |
C |
49 |
M
50 |
51 |
52 |
85 |
86 |
87 |
88 |
89 |
90 |
110 |
111 |
112 |
124 |
128 |
129 |
--------------------------------------------------------------------------------
/docs/html/objects.inv:
--------------------------------------------------------------------------------
1 | # Sphinx inventory version 1
2 | # Project: python-csp
3 | # Version: 0.1
4 | csp.patterns mod patterns.html
5 | csp.tracer mod tracer.html
6 | csp.guards mod guards.html
7 | csp.builtins mod builtins.html
8 | mandelbrot mod mandelbrot.html
9 | csp.csp mod csp.html
10 | csp.builtins.Id function builtins.html
11 | csp.builtins.Generate function builtins.html
12 | csp.csp.Channel.enable method csp.html
13 | csp.csp.Alt.fair_select method csp.html
14 | csp.builtins.Multiply function builtins.html
15 | csp.csp.Channel.select method csp.html
16 | csp.builtins.Pow function builtins.html
17 | csp.builtins.RShift function builtins.html
18 | csp.builtins.Is_Not function builtins.html
19 | csp.builtins.Land function builtins.html
20 | csp.csp.Channel.is_selectable method csp.html
21 | csp.csp.Guard class csp.html
22 | mandelbrot.MAXITER data mandelbrot.html
23 | csp.csp.process function csp.html
24 | csp.builtins.GenerateFloats function builtins.html
25 | csp.builtins.Prefix function builtins.html
26 | csp.csp.Par class csp.html
27 | csp.builtins.Mux2 function builtins.html
28 | csp.builtins.Delta2 function builtins.html
29 | csp.builtins.Div function builtins.html
30 | csp.csp.Channel.get method csp.html
31 | csp.csp.Skip.is_selectable method csp.html
32 | csp.builtins.Lnand function builtins.html
33 | csp.builtins.Printer function builtins.html
34 | csp.builtins.Splitter function builtins.html
35 | mandelbrot.consume function mandelbrot.html
36 | csp.builtins.Is function builtins.html
37 | csp.builtins.Xor function builtins.html
38 | csp.builtins.Or function builtins.html
39 | csp.csp.Channel.read method csp.html
40 | csp.csp.forever function csp.html
41 | csp.builtins.Lxor function builtins.html
42 | csp.builtins.FloorDiv function builtins.html
43 | csp.csp.CSPProcess.run method csp.html
44 | csp.builtins.Ne function builtins.html
45 | csp.builtins.Geq function builtins.html
46 | csp.csp.Alt.poison method csp.html
47 | csp.csp.Channel class csp.html
48 | csp.csp.Channel.put method csp.html
49 | csp.csp.Par.terminate method csp.html
50 | mandelbrot.main function mandelbrot.html
51 | csp.builtins.Sub function builtins.html
52 | csp.builtins.Mul function builtins.html
53 | csp.csp.Skip.disable method csp.html
54 | csp.builtins.Neg function builtins.html
55 | csp.builtins.Fibonacci function builtins.html
56 | csp.guards.Timer class guards.html
57 | csp.csp.FileChannel.put method csp.html
58 | csp.builtins.And function builtins.html
59 | csp.csp.Alt.select method csp.html
60 | csp.csp.Guard.disable method csp.html
61 | csp.csp.Channel.write method csp.html
62 | csp.csp.Guard.is_selectable method csp.html
63 | csp.builtins.Pairs function builtins.html
64 | csp.builtins.LShift function builtins.html
65 | csp.builtins.Mult function builtins.html
66 | csp.guards.Timer.read method guards.html
67 | csp.csp.Guard.select method csp.html
68 | csp.csp.Guard.enable method csp.html
69 | csp.builtins.Clock function builtins.html
70 | csp.csp.Alt class csp.html
71 | csp.builtins.Lor function builtins.html
72 | csp.builtins.Sin function builtins.html
73 | mandelbrot.mandelbrot function mandelbrot.html
74 | csp.csp.CSPServer.run method csp.html
75 | csp.builtins.Lt function builtins.html
76 | csp.guards.Timer.sleep method guards.html
77 | csp.csp.Skip.enable method csp.html
78 | csp.builtins.Lnor function builtins.html
79 | csp.builtins.Lnot function builtins.html
80 | csp.builtins.FixedDelay function builtins.html
81 | csp.builtins.Succ function builtins.html
82 | mandelbrot.get_colour function mandelbrot.html
83 | csp.builtins.Nor function builtins.html
84 | csp.builtins.Not function builtins.html
85 | csp.csp.CSPServer class csp.html
86 | csp.builtins.Zeroes function builtins.html
87 | csp.builtins.Gt function builtins.html
88 | csp.csp.Alt.pri_select method csp.html
89 | csp.csp.Channel.disable method csp.html
90 | csp.csp.Par.start method csp.html
91 | csp.csp.Skip class csp.html
92 | csp.builtins.Leq function builtins.html
93 | csp.builtins.Pred function builtins.html
94 | csp.csp.FileChannel class csp.html
95 | csp.csp.Seq class csp.html
96 | csp.builtins.Blackhole function builtins.html
97 | csp.builtins.Mod function builtins.html
98 | csp.csp.FileChannel.get method csp.html
99 | csp.csp.Skip.select method csp.html
100 | csp.csp.Guard.poison method csp.html
101 | csp.csp.Seq.start method csp.html
102 | csp.csp.CSPProcess class csp.html
103 | csp.builtins.Sign function builtins.html
104 | csp.builtins.Cos function builtins.html
105 | csp.builtins.Nand function builtins.html
106 | csp.builtins.Eq function builtins.html
107 | csp.csp.Channel.poison method csp.html
108 | csp.builtins.Plus function builtins.html
109 |
--------------------------------------------------------------------------------
/docs/html/search.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | Search — python-csp v0.1 documentation
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
Search
45 |
46 |
47 |
48 | Please activate JavaScript to enable the search
49 | functionality.
50 |
51 |
52 |
53 | From here you can search these documents. Enter your search
54 | words into the box below and click "search". Note that the search
55 | function will automatically search for all of the words. Pages
56 | containing fewer words won't appear in the result list.
57 |
58 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
78 |
79 |
80 |
92 |
93 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/docs/html/tracer.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | Debugging with the tracer module — python-csp v0.1 documentation
9 |
10 |
11 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
Debugging with the tracer module
53 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
95 |
96 |
97 |
115 |
119 |
120 |
--------------------------------------------------------------------------------
/examples/barber/barber.py:
--------------------------------------------------------------------------------
1 | """
2 | Solution to the sleeping barber problem in python-csp.
3 |
4 | Copyright (C) Sarah Mount, 2010.
5 |
6 | This program is free software; you can redistribute it and/or
7 | modify it under the terms of the GNU General Public License
8 | as published by the Free Software Foundation; either version 2
9 | of the License, or (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have rceeived a copy of the GNU General Public License
17 | along with this program. If not, see .
18 | """
19 |
20 | __date__ = 'July 2010'
21 | __author__ = 'Sarah Mount '
22 |
23 |
24 | from csp.csp import *
25 | from csp.builtins import Printer
26 | from csp.guards import Timer
27 |
28 | from queue import BoundedQueue as Queue
29 |
30 |
31 | @process
32 | def generate_customers(out_chan, printer):
33 | import random
34 | customers = ['Michael Palin', 'John Cleese', 'Terry Jones',
35 | 'Terry Gilliam', 'Graham Chapman']
36 | while True:
37 | python = random.choice(customers)
38 | printer.write('{0} needs a good shave!'.format(python))
39 | out_chan.write(python)
40 |
41 |
42 | @process
43 | def barber(door, printer):
44 | import random
45 | timer = Timer()
46 | while True:
47 | printer.write('Barber is sleeping.')
48 | customer = door.read()
49 | print_c.write('The barber has woken to give {0} a shave.'.format(customer))
50 | timer.sleep(random.random() * 5)
51 |
52 |
53 | @process
54 | def main(max_chairs):
55 | door_in, door_out = Channel(), Channel()
56 | printer = Channel()
57 | Par(generate_customers(door_in, printer),
58 | Queue(door_in, door_out, max_chairs),
59 | barber(door_out, printer)).start()
60 |
61 |
62 | if __name__ == '__main__':
63 | # Start simulation with 5 chairs in waiting room.
64 | main(5).start()
65 |
--------------------------------------------------------------------------------
/examples/barber/kbox.occ:
--------------------------------------------------------------------------------
1 | -- (c) Michael Sparks
2 |
3 | PROC box_with_maxsize(CHAN in, out) =
4 | CHAN pass_through, send_next
5 | PAR
6 | VAR head, tail, count, queue[n]:
7 | SEQ
8 | head := 0
9 | tail := 0
10 | count := 0
11 | WHILE TRUE:
12 | ALT
13 | (count < n) & in ? queue[tail] -- Input process - always ready to accept, for a sufficiently large value of n
14 | PAR -- Always accept values from sender up to queue size
15 | tail := (tail + 1) \ n
16 | count := count + 1
17 | (count > 0) & send_next ? ANY -- Pass through process
18 | SEQ -- Send on messages when reciever requests one
19 | pass_through ! queue[head]
20 | PAR
21 | head := (head + 1) \n
22 | count := count - 1
23 | WHILE TRUE -- Actual output process. Always ready to send if there's a value to send
24 | VAR x: -- In place of an output guard. Requests messages when not waiting to send a value
25 | SEQ
26 | send_next ! ANY -- Request next message from pass through process
27 | pass_through ? x -- Read value from pass_through process to send forward
28 | out ! x -- Send to out the value
--------------------------------------------------------------------------------
/examples/boids/boidprocs-obstacles.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boidprocs-obstacles.dia
--------------------------------------------------------------------------------
/examples/boids/boidprocs.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boidprocs.dia
--------------------------------------------------------------------------------
/examples/boids/boids-part1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boids-part1.png
--------------------------------------------------------------------------------
/examples/boids/boids-part2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boids-part2.png
--------------------------------------------------------------------------------
/examples/boids/boids-part3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boids-part3.png
--------------------------------------------------------------------------------
/examples/boids/boids-part4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boids-part4.png
--------------------------------------------------------------------------------
/examples/boids/boids-sliders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/boids-sliders.png
--------------------------------------------------------------------------------
/examples/boids/part1-classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/part1-classes.png
--------------------------------------------------------------------------------
/examples/boids/part1.py:
--------------------------------------------------------------------------------
1 | """
2 | Boids simulation using python-csp and pygame.
3 |
4 | Part 1 -- Setting up Pygame.
5 |
6 | Copyright (C) Sarah Mount, 2009.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program; if not, write to the Free Software
20 | """
21 |
22 | from csp.csp import *
23 |
24 | __author__ = 'Sarah Mount '
25 | __date__ = 'October 2009'
26 |
27 |
28 | @process
29 | def simulate(poschan, SIZE):
30 | """
31 | readset =
32 | writeset = poschan
33 | """
34 | centre = [random.randint(0, SIZE[0]), random.randint(0, SIZE[1])]
35 | while True:
36 | centre = random.randint(0, SIZE[0]), random.randint(0, SIZE[1])
37 | poschan.write(centre)
38 | return
39 |
40 |
41 | @process
42 | def drawboids(poschans, SIZE):
43 | """
44 | readset = poschans
45 | writeset =
46 | """
47 | import pygame
48 |
49 | FGCOL = (137, 192, 210, 100) # Foreground colour.
50 | BGCOL = pygame.Color('black') # Background colour.
51 | FPS = 60 # Maximum frames per second.
52 | CAPTION = 'python-csp example: Boids'
53 | FILENAME = 'boids.png' # Screenshot file.
54 | QUIT = False
55 |
56 | clock = pygame.time.Clock()
57 | dirty, last = [], []
58 | # chansize = len(poschans)
59 |
60 | pygame.init()
61 | screen = pygame.display.set_mode((SIZE[0], SIZE[1]), 0)
62 | pygame.display.set_caption(CAPTION)
63 |
64 | while not QUIT:
65 | ms_elapsed = clock.tick(FPS)
66 | print(ms_elapsed)
67 | dirty = last
68 | for rect in last: screen.fill(BGCOL, rect)
69 | last = []
70 | for channel in poschans:
71 | x, y = channel.read()
72 | rect = pygame.draw.circle(screen, FGCOL, (int(x), int(y)), 2, 0)
73 | dirty.append(rect)
74 | last.append(rect)
75 | pygame.display.update(dirty) # Update dirty rects.
76 | for event in pygame.event.get(): # Process events.
77 | if event.type == pygame.QUIT:
78 | QUIT = True
79 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
80 | pygame.image.save(screen, FILENAME)
81 | print('Saving boids in:', FILENAME)
82 | for chan in poschans: chan.poison()
83 | pygame.quit()
84 | return
85 |
86 |
87 | @process
88 | def main():
89 | NUMBOIDS = 100 # Number of boids in simulation.
90 | SIZE = (800, 600) # Screen size.
91 | # Set up channels for reporting boid positions / velocities.
92 | poschans = [Channel() for i in range(NUMBOIDS)]
93 | # Draw channel for the drawboids process.
94 | # drawchan = Channel()
95 | # Generate a list of all processes in the simulation.
96 | procs = [simulate(poschans[i], SIZE) for i in range(NUMBOIDS)]
97 | procs.append(drawboids(poschans, SIZE)) # Drawing process.
98 | simulation = Par(*procs) # Start simulation.
99 | simulation.start()
100 | return
101 |
102 |
103 | if __name__ == '__main__':
104 | main().start()
105 |
--------------------------------------------------------------------------------
/examples/boids/part2-classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/part2-classes.png
--------------------------------------------------------------------------------
/examples/boids/part2.py:
--------------------------------------------------------------------------------
1 | """
2 | Boids simulation using python-csp and pygame.
3 |
4 | Part 2 -- Adding movement to the boids.
5 |
6 | Copyright (C) Sarah Mount, 2009.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program; if not, write to the Free Software
20 | """
21 |
22 | from csp.csp import *
23 |
24 | __author__ = 'Sarah Mount '
25 | __date__ = 'October 2009'
26 |
27 |
28 | @process
29 | def simulate(poschan, SIZE):
30 | """
31 | readset =
32 | writeset = poschan
33 | """
34 | centre = [random.randint(0, SIZE[0]), random.randint(0, SIZE[1])]
35 | default_velocity = [random.choice((-1.0, 0.0, 1.0)),
36 | random.choice((-1.0, 0.0, 1.0))]
37 | velocity = default_velocity
38 | while True:
39 | centre = [centre[0] + velocity[0],
40 | centre[1] + velocity[1]]
41 | # Wrap the screen.
42 | if centre[0]<0: centre[0] += SIZE[0]
43 | elif centre[0]>SIZE[0]: centre[0] -= SIZE[0]
44 | if centre[1]<0: centre[1] += SIZE[1]
45 | elif centre[1]>SIZE[1]: centre[1] -= SIZE[1]
46 | # Write to the drawing process.
47 | poschan.write(centre)
48 | return
49 |
50 |
51 | @process
52 | def drawboids(poschans, SIZE):
53 | """
54 | readset = poschans
55 | writeset =
56 | """
57 | import pygame
58 |
59 | FGCOL = (137, 192, 210, 100) # Foreground colour.
60 | BGCOL = pygame.Color('black') # Background colour.
61 | FPS = 60 # Maximum frames per second.
62 | CAPTION = 'python-csp example: Boids'
63 | FILENAME = 'boids.png' # Screenshot file.
64 | QUIT = False
65 |
66 | clock = pygame.time.Clock()
67 | dirty, last = [], []
68 | # chansize = len(poschans)
69 |
70 | pygame.init()
71 | screen = pygame.display.set_mode((SIZE[0], SIZE[1]), 0)
72 | pygame.display.set_caption(CAPTION)
73 |
74 | while not QUIT:
75 | ms_elapsed = clock.tick(FPS)
76 | print(ms_elapsed)
77 | dirty = last
78 | for rect in last: screen.fill(BGCOL, rect)
79 | last = []
80 | for channel in poschans:
81 | x, y = channel.read()
82 | rect = pygame.draw.circle(screen, FGCOL, (int(x), int(y)), 2, 0)
83 | dirty.append(rect)
84 | last.append(rect)
85 | pygame.display.update(dirty) # Update dirty rects.
86 | for event in pygame.event.get(): # Process events.
87 | if event.type == pygame.QUIT:
88 | QUIT = True
89 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
90 | pygame.image.save(screen, FILENAME)
91 | print('Saving boids in:', FILENAME)
92 | for chan in poschans: chan.poison()
93 | pygame.quit()
94 | return
95 |
96 |
97 | @process
98 | def main():
99 | NUMBOIDS = 100 # Number of boids in simulation.
100 | SIZE = (800, 600) # Screen size.
101 | # Set up channels for reporting boid positions / velocities.
102 | poschans = [Channel() for i in range(NUMBOIDS)]
103 | # Draw channel for the drawboids process.
104 | # drawchan = Channel()
105 | # Generate a list of all processes in the simulation.
106 | procs = [simulate(poschans[i], SIZE) for i in range(NUMBOIDS)]
107 | procs.append(drawboids(poschans, SIZE)) # Drawing process.
108 | simulation = Par(*procs) # Start simulation.
109 | simulation.start()
110 | return
111 |
112 |
113 | if __name__ == '__main__':
114 | main().start()
115 |
--------------------------------------------------------------------------------
/examples/boids/part3-classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/part3-classes.png
--------------------------------------------------------------------------------
/examples/boids/part4-classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/examples/boids/part4-classes.png
--------------------------------------------------------------------------------
/examples/builtins/builtin-example.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 |
4 | from csp.csp import *
5 | from csp.builtins import Fibonacci, Generate, Multiply, Printer
6 |
7 |
8 | if __name__ == '__main__':
9 | c = []
10 | c.append(Channel())
11 | c.append(Channel())
12 | c.append(Channel())
13 |
14 | f = Fibonacci(c[0])
15 | g = Generate(c[1])
16 | m = Multiply(c[0],c[1],c[2])
17 | p = Printer(c[2])
18 |
19 | par = Par(f,g,m,p)
20 | par.start()
21 |
22 |
--------------------------------------------------------------------------------
/examples/circuits/fulladder.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """Python CSP full adder.
4 |
5 | Based on code from PyCSP - Communicating Sequential Processes for
6 | Python. John Markus Bjorndalen, Brian Vinter, Otto Anshus. CPA 2007,
7 | Surrey, UK, July 8-11, 2007. IOS Press 2007, ISBN 978-1-58603-767-3,
8 | Concurrent Systems Engineering Series (ISSN 1383-7575).
9 |
10 | Copyright (C) Sarah Mount, 2009.
11 |
12 | This program is free software; you can redistribute it and/or
13 | modify it under the terms of the GNU General Public License
14 | as published by the Free Software Foundation; either version 2
15 | of the License, or (at your option) any later version.
16 |
17 | This program is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You should have rceeived a copy of the GNU General Public License
23 | along with this program; if not, write to the Free Software
24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 | """
26 |
27 | __author__ = 'Sarah Mount '
28 | __date__ = 'December 2008'
29 |
30 |
31 | from csp.csp import *
32 | from csp.builtins import *
33 |
34 | @process
35 | def Bool1(cout):
36 | """
37 | readset =
38 | writeset = cout
39 | """
40 | while True:
41 | cout.write(1)
42 | cout.write(1)
43 | cout.write(0)
44 | cout.write(0)
45 | return
46 |
47 | @process
48 | def Bool2(cout):
49 | """
50 | readset =
51 | writeset = cout
52 | """
53 | while True:
54 | cout.write(1)
55 | cout.write(0)
56 | cout.write(1)
57 | cout.write(0)
58 | return
59 |
60 | def fulladder(A_in, B_in, C_in, Sum_in, Carry_in):
61 | """Full adder implementation.
62 |
63 | Based on Bjorndalen, Vinter & Anshus (2007).
64 | """
65 | Aa = Channel()
66 | Ab = Channel()
67 | Ba = Channel()
68 | Bb = Channel()
69 | Ca = Channel()
70 | Cb = Channel()
71 | i1 = Channel()
72 | i1a = Channel()
73 | i1b = Channel()
74 | i2 = Channel()
75 | i3 = Channel()
76 |
77 | return Par(Delta2(A_in, Aa, Ab),
78 | Delta2(B_in, Ba, Bb),
79 | Delta2(C_in, Ca, Cb),
80 | Delta2(i1, i1a, i1b),
81 | Xor(Aa, Ba, i1),
82 | Xor(i1a, Ca, Sum_in),
83 | And(Ab, Bb, i2),
84 | And(i1b, Cb, i3),
85 | Or(i2, i3, Carry_in))
86 |
87 | if __name__ == '__main__':
88 | print('\nFull adder implemented in Python CSP\n')
89 | # Inputs to full adder
90 | A = Channel()
91 | B = Channel()
92 | Cin = Channel()
93 | # Outputs of full adder
94 | Carry = Channel()
95 | Sum = Channel()
96 | # Channels for printing to STDOUT
97 | PCarry = Channel()
98 | PSum = Channel()
99 | # Create and start adder
100 | adder = Par(Bool1(A),
101 | Bool2(B),
102 | Zeroes(Cin),
103 | fulladder(A, B, Cin, Sum, Carry),
104 | Sign(Carry, PCarry, 'Carry: '),
105 | Printer(PCarry),
106 | Sign(Sum, PSum, 'Sum: '),
107 | Printer(PSum))
108 | adder.start()
109 |
110 |
111 |
--------------------------------------------------------------------------------
/examples/matrix/matrix.py:
--------------------------------------------------------------------------------
1 |
2 | #!/usr/bin/env python
3 |
4 | # FIXME: Nowhere near PEP8 compatible :(
5 |
6 | from csp.csp import *
7 |
8 |
9 | def calculateRowColumnProduct(self, A, row, B, col):
10 | product = 0
11 | for i in range(len(A[row])):
12 | product += A[row][i] * B[i][col]
13 | return product
14 |
15 | @process
16 | def ParcalculateRowColumnProduct(cout, A, row, B, col):
17 | """
18 | readset =
19 | writeset = cout
20 | """
21 | product = 0
22 | for i in range(len(A[row])):
23 | product += A[row][i] * B[i][col]
24 | cout.write((row,col,product))
25 |
26 | class Matrix():
27 | def __init__(self, h, k):
28 | self.matrix = []
29 | for i in range(h):
30 | row = []
31 | for j in range(k):
32 | row.append(0)
33 |
34 | self.matrix.append(row)
35 |
36 | def Multiply(self, mb):
37 | b = mb.matrix
38 | a = self.matrix
39 | if len(a[0]) != len(b):
40 | raise Exception()
41 | return
42 |
43 | mat = Matrix(len(a),len(b[0]))
44 | for i in range(len(a)) :
45 | for j in range(len(b[0])):
46 | mat.matrix[i][j] = calculateRowColumnProduct(self,a,i,b,j)
47 |
48 | return mat
49 |
50 | def ParMultiply(self, mb):
51 | b = mb.matrix
52 | a = self.matrix
53 | if len(a[0]) != len(b):
54 | raise Exception()
55 | return
56 |
57 | procs = []
58 | chnls = []
59 | mat = Matrix(len(a),len(b[0]))
60 | for i in range(len(a)) :
61 | for j in range(len(b[0])):
62 | ch = Channel()
63 | chnls.append(ch);
64 | procs.append(ParcalculateRowColumnProduct(ch,a,i,b,j))
65 |
66 |
67 | p = Par(*procs);
68 | p.start();
69 |
70 | alt = Alt(*chnls)
71 |
72 | for i in range(len(chnls)):
73 | a,b,ans = alt.select()
74 |
75 | mat.matrix[a][b] = ans
76 | alt.poison()
77 |
78 | return mat
79 |
80 | def createID(self):
81 | for i in range(len(self.matrix)) :
82 | for j in range(len(self.matrix[0])):
83 | if i == j:
84 | self.matrix[i][j] = 1
85 | else :
86 | self.matrix[i][j] = 0
87 |
88 | def printMatrix(self):
89 | print(self.matrix)
90 |
91 |
92 | if __name__ == '__main__':
93 | i = Matrix(3,3)
94 | g = Matrix(3,3)
95 | i.createID()
96 | g.createID()
97 | j = i.Multiply(g)
98 | j.printMatrix();
99 | j = i.ParMultiply(g)
100 | j.printMatrix()
101 |
102 | print("")
103 |
--------------------------------------------------------------------------------
/examples/monte_carlo/pi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from csp.csp import *
4 | from math import sqrt
5 | from decimal import Decimal
6 |
7 |
8 |
9 | def genPair():
10 | return random.random(),random.random()
11 |
12 | g = lambda x: sqrt(1-(x*x))
13 |
14 |
15 | perProcess = 100000
16 |
17 | workers = 320
18 |
19 | @process
20 | def worker(c):
21 | """
22 | readset =
23 | writeset = c
24 | """
25 | count = 0
26 | i = 0
27 | while i < perProcess:
28 | x,y = genPair()
29 | if y<= g(x) :
30 | count = count + 1
31 | i += 1
32 | c.write((Decimal(count)))
33 | return
34 |
35 | @process
36 | def consumer(cins):
37 | """
38 | readset = cins
39 | writeset =
40 | """
41 | alt = Alt(*cins)
42 | total = Decimal(0)
43 | for i in range(len(cins)):
44 | t = alt.select()
45 | total += t
46 |
47 | print("Pi aproximation: " + str( Decimal((total/(perProcess*workers))*4) ) )
48 |
49 | def main():
50 | Chnls, procs = [],[]
51 | for i in range(workers):
52 | Chnls.append(Channel())
53 | procs.append(worker(Chnls[i]))
54 |
55 | procs.append(consumer(Chnls))
56 | p = Par(*procs)
57 | p.start()
58 | return
59 |
60 | if __name__ == '__main__':
61 | getcontext().prec = 19
62 | t0 = time.time()
63 | main()
64 | t1 = time.time()
65 | print("Time Taken: " + str ( t1 - t0 ) )
66 |
--------------------------------------------------------------------------------
/examples/sensors/dsp.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Digital signal processing for python-csp.
5 |
6 | Copyright (C) Sarah Mount, 2009.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | from csp.csp import *
23 |
24 | import math
25 |
26 | # TODO: Use numpy for more sophisticated processes.
27 |
28 | ACCEL_DUE_TO_GRAVITY = 9.80665
29 |
30 |
31 | @forever
32 | def Zip(outchan, inchannels, _process=None):
33 | """Take data from a number of input channels, and write that
34 | data as a single list to L{outchan}.
35 | """
36 | while True:
37 | outchan.write([chan.read() for chan in inchannels])
38 | yield
39 | return
40 |
41 |
42 | @forever
43 | def Unzip(inchan, outchans, _process=None):
44 | """Continuously read tuples of data from a single input channel and send
45 | each datum out down its own output channel.
46 | """
47 | while True:
48 | data = inchan.read()
49 | for i in range(data):
50 | outchans[i].write(data[i])
51 | yield
52 | return
53 |
54 |
55 | @forever
56 | def Sin(inchan, outchan, _process=None):
57 | while True:
58 | outchan.write(math.sin(inchan.read()))
59 | yield
60 | return
61 |
62 |
63 | @forever
64 | def Cos(inchan, outchan, _process=None):
65 | while True:
66 | outchan.write(math.cos(inchan.read()))
67 | yield
68 | return
69 |
70 |
71 | @forever
72 | def Tan(inchan, outchan, _process=None):
73 | while True:
74 | outchan.write(math.tan(inchan.read()))
75 | yield
76 | return
77 |
78 |
79 | @forever
80 | def GenerateFloats(outchan, _process=None):
81 | x = 0.0
82 | while True:
83 | outchan.write(x)
84 | x += 0.1
85 | yield
86 | return
87 |
88 |
89 | @forever
90 | def Magnitude(inchan, outchan, _process=None):
91 | while True:
92 | acceldata = inchan.read()
93 | mag = 0.0
94 | for axis in acceldata: mag += axis ** 2
95 | outchan.write(math.sqrt(mag))
96 | yield
97 | return
98 |
99 |
100 | @forever
101 | def Difference(inchan, outchan, window=1, _process=None):
102 | cache = 0.0
103 | while True:
104 | acceldata = inchan.read()
105 | try:
106 | outchan.write(acceldata - cache)
107 | cache = acceldata
108 | except IndexError:
109 | pass
110 | yield
111 | return
112 |
113 |
114 | @forever
115 | def Square(inchan, outchan, _process=None):
116 | while True:
117 | data = inchan.read()
118 | outchan.write(data ** 2)
119 | yield
120 | return
121 |
122 |
123 | @forever
124 | def Normalise(inchan, outchan, _process=None, start=0.0, end=100.0):
125 | scale = end - start
126 | while True:
127 | outchan.write(inchan.read() / scale)
128 | yield
129 | return
130 |
131 |
132 | @forever
133 | def Threshold(thresh, inchan, outchan, _process=None):
134 | while True:
135 | mag = inchan.read()
136 | if mag >= thresh:
137 | outchan.write(mag)
138 | yield
139 | return
140 |
141 |
142 |
--------------------------------------------------------------------------------
/examples/sensors/oak_oscope.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Chart the output of a Toradex Oak accelerometer.
5 |
6 | Copyright (C) Sarah Mount, 2009.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | __author__ = 'Sarah Mount '
23 | __date__ = 'November 2009'
24 | __version__ = '0.2'
25 |
26 | from oscilloscope import Oscilloscope
27 |
28 | def chart_accel():
29 | """Requires a Toradex Oak G to be attached to a USB port."""
30 | import dsp
31 | from toradex_csp import Accelerometer
32 | channels = [Channel() for i in range(7)]
33 | par = Par(Accelerometer(channels[0]),
34 | dsp.Unzip(channels[0], (channels[0:3])),
35 | Blackhole(channels[1]),
36 | Blackhole(channels[2]),
37 | dsp.Difference(channels[1], channels[2]),
38 | dsp.Square(channels[2], channels[3]),
39 | Oscilloscope(channels[3]))
40 | par.start()
41 | return
42 |
43 |
44 | if __name__ == '__main__':
45 | chart_accel()
46 |
--------------------------------------------------------------------------------
/exstatic/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/exstatic/__init__.py
--------------------------------------------------------------------------------
/exstatic/cspwarnings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Exstatic errors and warnings for CSP.
5 |
6 | TODO: Document this module.
7 |
8 | Copyright (C) Sarah Mount, 2010.
9 |
10 | This program is free software; you can redistribute it and/or
11 | modify it under the terms of the GNU General Public License
12 | as published by the Free Software Foundation; either version 2
13 | of the License, or (at your option) any later version.
14 |
15 | This program is distributed in the hope that it will be useful,
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | GNU General Public License for more details.
19 |
20 | You should have rceeived a copy of the GNU General Public License
21 | along with this program. If not, see .
22 | """
23 |
24 | import exstatic.warnings
25 |
26 | __all__ = ['errcodes', 'list_error_codes', 'create_error', 'reset_errors',
27 | 'get_errors', 'print_errors']
28 |
29 | errcodes = {
30 | # Information.
31 | 'I001':'Function is a CSP process or server process',
32 | # Warnings.
33 | 'W001':'Channel in both readset and writeset.',
34 | 'W002':'No readset given in documentation.',
35 | 'W003':'No writeset given in documentation.',
36 | 'W004':'@process or @forever applied to method (rather than function)',
37 | # Errors.
38 | 'E001':'Process / forever decorator wraps a method, not a function.',
39 | 'E002':'Channel in readset is not a formal parameter to this process.',
40 | 'E003':'Channel in writeset is not a formal parameter to this process.',
41 | 'E004':'Channel appears in documented readset but not read from in function body.',
42 | 'E005':'Channel is read from in function body but does not appear in documented readset',
43 | 'E006':'Channel appears in documented writeset but not written to in function body.',
44 | 'E007':'Channel is written to in function body but does not appear in documented writeset'
45 | }
46 |
47 |
48 | csp_error_list = exstatic.warnings.ExstaticErrorList(errcodes)
49 |
50 |
51 | def list_error_codes():
52 | """List all available error codes.
53 | """
54 | sep = '--------------------------------------------------------------------'
55 | print ( sep )
56 | print ( ' CODE | MESSAGE' )
57 | codes = list(errcodes.keys())
58 | codes.sort()
59 | current_type = ''
60 | for key in codes:
61 | if key[0] != current_type:
62 | print ( sep )
63 | print ( str ( key ) + ': |' + str ( errcodes[key] ) )
64 | current_type = key[0]
65 | print ( sep )
66 | return
67 |
68 |
69 | def create_error(filename, lineno, scope, errcode):
70 | """Create a new error and add it to the list.
71 | """
72 | return csp_error_list.create_error(filename, lineno, scope, errcode)
73 |
74 |
75 | def reset_errors():
76 | """Empty the current error list of all errors.
77 | """
78 | csp_error_list.reset_errors()
79 | return
80 |
81 |
82 | def get_errors(excluded=[]):
83 | """Return the list of current errors.
84 |
85 | @return list of current errors.
86 | @type list
87 | """
88 | return csp_error_list.get_errors(excluded=excluded)
89 |
90 | def print_errors(excluded=[]):
91 | """Print the list of current errors.
92 | """
93 | csp_error_list.print_errors(excluded=excluded)
94 | return
95 |
--------------------------------------------------------------------------------
/exstatic/py2icode.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | py2icode.py produces an ICODE representation of a Python file.
5 |
6 | Usage: py2icode.py ?
7 |
8 | should be a python file for processing. The full path is not
9 | needed. is the name of the file which should store the
10 | ICODE translation of . If no name is given STDOUT is used.
11 | """
12 |
13 | __author__ = 'Sarah Mount '
14 | __date__ = '2010-05-16'
15 |
16 |
17 | DEBUG = True
18 |
19 | import ast, sys
20 | from pyicode import *
21 |
22 | __all__ = ['Ast2IcodeVisitor']
23 |
24 | class Ast2IcodeVisitor(ast.NodeTransformer):
25 | """
26 | AST Visitor which creates an ICODE translation of the AST, stored
27 | in its icode attribute.
28 | """
29 | def __init__(self):
30 | super(AST2ICODEVisitor, self)
31 | self.icode = '' # BAH
32 |
33 | def vist_Function(self, node):
34 | pass
35 |
36 |
37 | # def default(self, node):
38 | # """Gives debug info in place of unwritten visit methods."""
39 | # self.generic_visit(node)
40 | # return node
41 | # self.icode += "\nDEBUG: START NODE\n"
42 | # self.icode += '\t__repr__:' + node.__repr__() + '\n'
43 | # self.icode += '\t__dict__:' + str(node.__dict__) + '\n'
44 | # self.icode += "DEBUG: END NODE\n"
45 |
46 |
47 | if __name__ == '__main__':
48 | if DEBUG: print ( 'Debugging: ON. Script arguments:' + str ( sys.argv ) )
49 | # Determine the input file.
50 | if len(sys.argv) == 1:
51 | print ( 'You must specify a Python file for processing.' )
52 | sys.exit(1)
53 | else:
54 | i_file = sys.argv[1]
55 | # Determine the output file. Use sys.stdout if none specified.
56 | if len(sys.argv) > 2:
57 | o_file = sys.argv[2]
58 | o_fd = open(sys.argv[2], 'w')
59 | if DEBUG: print ( 'Output file:' + str ( sys.argv[2] ) )
60 | else:
61 | if DEBUG: print ( 'Using STDOUT for output.' )
62 | o_file = ''
63 | o_fd = sys.stdout
64 | # This is the important stuff.
65 | infile = open(i_file).read()
66 | tree = compile(infile, '', 'exec')#, ast.PyCF_ONLY_AST)
67 | outtree = AST2ICODEVisitor().visit(tree)
68 | o_fd.write(outtree.xml())
69 | if not o_file == '':
70 | o_fd.close()
71 | # ...end of important stuff.
72 |
73 | ####################################################################
74 | # SCRATCH SPACE #
75 | ####################################################################
76 | #
77 | # self.icode += "\tSTART CHILD NODES\n"
78 | # for i in node.getChildNodes():
79 | # self.icode += '\t\t__repr__:' + i.__repr__() + '\n'
80 | # self.icode += '\t\t__dict__:' + str(i.__dict__) + '\n'
81 | # self.dispatch(i)
82 | # self.icode += "\tEND CHILD NODES\n"
83 |
84 |
85 |
86 | ############# SCRATCH
87 | # def visit_Const(self, node):
88 | # self.generic_visit(node)
89 | # return IcodeConst(node.value, lineno=node.lineno)
90 |
91 | # def visit_Assign(self, node):
92 | # print 'ASSIGN'
93 | # for key,val in node.__dict__.items():
94 | # print key, val
95 | # print 'END'
96 | # self.generic_visit(node)
97 | # return IcodeAssign(node.nodes, node.expr, lineno=node.lineno)
98 |
99 | # def visit_Import(self, node):
100 | # self.generic_visit(node)
101 | # return IcodeImport(node.names)
102 |
103 |
104 |
--------------------------------------------------------------------------------
/exstatic/stack.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Generic stack type for Python.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 |
23 | __all__ = ['Stack']
24 |
25 | class Stack:
26 |
27 | def __init__(self):
28 | self.__stack = []
29 | return
30 |
31 | def push(self, value):
32 | self.__stack.append(value)
33 | return
34 |
35 | def pop(self):
36 | assert(len(self.__stack) > 0)
37 | return self.__stack.pop()
38 |
39 | def peek(self):
40 | assert(len(self.__stack) > 0)
41 | return self.__stack[len(self.__stack) - 1]
42 |
43 | def issubset(self, other):
44 | """Determine whether other stack is a subset of this one.
45 | Order matters.
46 | """
47 | size = min(len(self.__stack), len(other))
48 | for i in range(size):
49 | if not self.__stack[i] == other[i]:
50 | return False
51 | return True
52 |
53 | def __contains__(self, item):
54 | return item in self.__stack
55 |
56 | def __len__(self):
57 | return len(self.__stack)
58 |
59 | def __getitem__(self, index):
60 | return self.__stack[index]
61 |
62 | def __iter__(self):
63 | return self.__stack.__iter__()
64 |
65 | def __repr__(self):
66 | return self.__stack.__repr__()
67 |
68 | def __str__(self):
69 | return self.__stack.__str__()
70 |
71 |
--------------------------------------------------------------------------------
/exstatic/warnings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Generic warnings and errors for Exstatic.
5 |
6 | TODO: Document this module.
7 |
8 | Copyright (C) Sarah Mount, 2010.
9 |
10 | This program is free software; you can redistribute it and/or
11 | modify it under the terms of the GNU General Public License
12 | as published by the Free Software Foundation; either version 2
13 | of the License, or (at your option) any later version.
14 |
15 | This program is distributed in the hope that it will be useful,
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | GNU General Public License for more details.
19 |
20 | You should have rceeived a copy of the GNU General Public License
21 | along with this program. If not, see .
22 | """
23 |
24 | __author__ = 'Sarah Mount '
25 | __date__ = 'May 2010'
26 |
27 | import os.path
28 | import sys
29 |
30 | severity = {'I':'Information', 'W':'Warning', 'E':'Error'}
31 |
32 |
33 | __all__ = ['severity', 'ExstaticErrorList', 'ExstaticError',
34 | 'ExstaticErrorFactory']
35 |
36 |
37 | class ExstaticErrorList(object):
38 |
39 | def __init__(self, errcodes):
40 | self.error_factory = ExstaticErrorFactory(errcodes)
41 | self.errors = []
42 | return
43 |
44 | def create_error(self, filename, lineno, scope, errcode):
45 | error = self.error_factory.create_error(filename, lineno, scope, errcode)
46 | self.errors.append(error)
47 | return
48 |
49 | def get_errors(self, excluded=[]):
50 | """Return a list of the current errors, excluding any in the
51 | excluded set.
52 | """
53 | errors = []
54 | for error in self.errors:
55 | if not error.errcode in excluded:
56 | errors.append(error)
57 | return errors
58 |
59 | def print_errors(self, out=sys.stdout, excluded=[]):
60 | """Print a list of the current errors, excluding any in the
61 | excluded set.
62 | """
63 | for error in self.errors:
64 | if not error.errcode in excluded:
65 | out.write(str(error))
66 | out.write('\n')
67 | return
68 |
69 | def reset_errors(self):
70 | self.errors = []
71 | return
72 |
73 |
74 | class ExstaticErrorFactory(object):
75 |
76 | def __init__(self, errcodes):
77 | """
78 | @param errcodes dictionary of error codes -> explainations
79 | """
80 | self.errcodes = errcodes
81 | return
82 |
83 | def create_error(self, filename, lineno, scope, errcode):
84 | """Create and return a new error.
85 | """
86 | obj = ExstaticError(filename, lineno, scope, errcode)
87 | obj.set_explaination(self.errcodes[errcode])
88 | return obj
89 |
90 |
91 | class ExstaticError(object):
92 |
93 | def __init__(self, filename, lineno, scope, errcode):
94 | """
95 | @param filename: name of the file in which error occurs
96 | @param lineno: line number on which error occurs
97 | @param scope: scope that the error occurs in (e.g. function name)
98 | @param errcode: name of this particular error
99 | """
100 | self.filename = os.path.basename(filename)
101 | self.lineno = lineno
102 | self.scope = scope
103 | self.errcode = errcode
104 | self.explaination = ''
105 | return
106 |
107 | def get_severity(self):
108 | """
109 | @return 'E' for an error and 'W' for a warning.
110 | """
111 | return severity[self.errcode[0]]
112 |
113 | def set_explaination(self, explain):
114 | self.explaination = explain
115 | return
116 |
117 | def __str__(self):
118 | return '[{0}:{1}] {2} ({3}, {4}): {5}'.format(self.filename,
119 | self.lineno,
120 | self.get_severity(),
121 | self.errcode,
122 | self.scope,
123 | self.explaination)
124 |
125 |
--------------------------------------------------------------------------------
/gadget/readme.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/logo/logo-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/logo/logo-square.png
--------------------------------------------------------------------------------
/logo/pythoncsp-docs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/logo/pythoncsp-docs.png
--------------------------------------------------------------------------------
/logo/pythoncsp-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/logo/pythoncsp-logo.png
--------------------------------------------------------------------------------
/logo/pythoncsp-logo.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/logo/pythoncsp-logo.xcf
--------------------------------------------------------------------------------
/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | REM Command file for Sphinx documentation
4 |
5 | set SPHINXBUILD=sphinx-build
6 | set ALLSPHINXOPTS=-d build/doctrees %SPHINXOPTS% rst
7 | if NOT "%PAPER%" == "" (
8 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
9 | )
10 |
11 | if "%1" == "" goto help
12 |
13 | if "%1" == "help" (
14 | :help
15 | echo.Please use `make ^` where ^ is one of
16 | echo. html to make standalone HTML files
17 | echo. dirhtml to make HTML files named index.html in directories
18 | echo. pickle to make pickle files
19 | echo. json to make JSON files
20 | echo. htmlhelp to make HTML files and a HTML help project
21 | echo. qthelp to make HTML files and a qthelp project
22 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
23 | echo. changes to make an overview over all changed/added/deprecated items
24 | echo. linkcheck to check all external links for integrity
25 | echo. doctest to run all doctests embedded in the documentation if enabled
26 | goto end
27 | )
28 |
29 | if "%1" == "clean" (
30 | for /d %%i in (build\*) do rmdir /q /s %%i
31 | del /q /s build\*
32 | goto end
33 | )
34 |
35 | if "%1" == "html" (
36 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% build/html
37 | echo.
38 | echo.Build finished. The HTML pages are in build/html.
39 | goto end
40 | )
41 |
42 | if "%1" == "dirhtml" (
43 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% build/dirhtml
44 | echo.
45 | echo.Build finished. The HTML pages are in build/dirhtml.
46 | goto end
47 | )
48 |
49 | if "%1" == "pickle" (
50 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% build/pickle
51 | echo.
52 | echo.Build finished; now you can process the pickle files.
53 | goto end
54 | )
55 |
56 | if "%1" == "json" (
57 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% build/json
58 | echo.
59 | echo.Build finished; now you can process the JSON files.
60 | goto end
61 | )
62 |
63 | if "%1" == "htmlhelp" (
64 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% build/htmlhelp
65 | echo.
66 | echo.Build finished; now you can run HTML Help Workshop with the ^
67 | .hhp project file in build/htmlhelp.
68 | goto end
69 | )
70 |
71 | if "%1" == "qthelp" (
72 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% build/qthelp
73 | echo.
74 | echo.Build finished; now you can run "qcollectiongenerator" with the ^
75 | .qhcp project file in build/qthelp, like this:
76 | echo.^> qcollectiongenerator build\qthelp\python-csp.qhcp
77 | echo.To view the help file:
78 | echo.^> assistant -collectionFile build\qthelp\python-csp.ghc
79 | goto end
80 | )
81 |
82 | if "%1" == "latex" (
83 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% build/latex
84 | echo.
85 | echo.Build finished; the LaTeX files are in build/latex.
86 | goto end
87 | )
88 |
89 | if "%1" == "changes" (
90 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% build/changes
91 | echo.
92 | echo.The overview file is in build/changes.
93 | goto end
94 | )
95 |
96 | if "%1" == "linkcheck" (
97 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% build/linkcheck
98 | echo.
99 | echo.Link check complete; look for any errors in the above output ^
100 | or in build/linkcheck/output.txt.
101 | goto end
102 | )
103 |
104 | if "%1" == "doctest" (
105 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% build/doctest
106 | echo.
107 | echo.Testing of doctests in the sources finished, look at the ^
108 | results in build/doctest/output.txt.
109 | goto end
110 | )
111 |
112 | :end
113 |
--------------------------------------------------------------------------------
/maketags.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | find . -name *.py -print -or -name *.html -print | xargs etags
4 |
--------------------------------------------------------------------------------
/rst/Tutorial.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp tutorial (front page).
2 | #labels Featured,Phase-Support,Tutorial
3 |
4 |
5 |
6 | This page should give you an birds-eye view of CSP and the python-csp
7 | library. The tutorial pages that follow take you through installing
8 | the library and using it in some detail, with several medium sized
9 | example programs (and exercises!).
10 |
11 | = What is CSP? =
12 |
13 | Concurrent and parallel programming are generally seen as "difficult"
14 | tasks. This is partly because most people have a mental model of how
15 | computers work which is fundamentally sequential, and partly because
16 | concurrent programs are susceptible to errors such as race hazards,
17 | deadlocks, and so on.
18 |
19 | CSP stands for Communicating Sequential Processes, which is a
20 | framework for writing concurrent or program via _message
21 | passinge_. The advantage of message passing is that it makes race
22 | hazards impossible and provides a model of concurrency that is much
23 | easier to think about and more fun to program with.
24 |
25 |
26 | = Why CSP for Python? =
27 |
28 | Python currently has some support for threaded concurrency via the
29 | `thread` and `threading` module, support for parallel programming and
30 | the `processing` module. Threads are very low level, difficult to work
31 | with and cannot take advantage of multicore architectures that are now
32 | becoming commonplace. The `processing` module provides good support
33 | for process and thread-safe data structures but neither provide
34 | support for the message passing paradigm of programming and the sorts
35 | of constructs common to CSP style languages (such as OCCAM, OCCAM-pi,
36 | JCSP, C++CSP and so on). python-csp is design to plug this gap and
37 | also to provide an idiomatically _pythonic_ implementation of the
38 | ideas in CSP.
39 |
40 |
41 | == CSP resources ==
42 |
43 | * [http://www.usingcsp.com/ CSP book] Hoare's original CSP book
44 | * [http://wotug.org/ WoTUG] The place for Communicating Processes
45 | * [http://books.google.co.uk/books?id=4ygZed-24LsC&printsec=frontcover&dq=communicating+sequential+processes&source=bl&ots=VfQoVDyIXn&sig=xDJ3FwyC82NSJ5J1bCMnkWPsS8M&hl=en&ei=c8K_S-K8HZX20gT618GWCQ&sa=X&oi=book_result&ct=result&resnum=12&ved=0CEYQ6AEwCw#v=onepage&q&f=false 25 years of CSP]
46 |
47 |
48 | == Other concurrency packages for Python ==
49 |
50 | * [http://code.google.com/p/pycsp/ PyCSP] is another CSP library for Python, and somewhat similar to python-csp. In the medium term it is intended that PyCSP and python-csp will merge.
51 | * [http://peak.telecommunity.com/DevCenter/Trellis Trellis] reactive programming for Python
52 | * [http://peak.telecommunity.com/DevCenter/TrellisSTM STM] software transactional memory for Python
53 | * [http://www.kamaelia.org/Home.html Kamaelia] message passing concurrency using asynchronous channels
54 | * [http://twistedmatrix.com/trac/ Twisted] event-driven Python programming
55 | * [http://docs.python.org/library/multiprocessing.html Multiprocessing] this is the best support in the current standard library for running forked processes.
56 |
57 |
58 |
59 | = Moving on: a python-csp tutorial =
60 |
61 | The rest of this tutorial assumes that you can already write Python code. If not, read
62 | [http://docs.python.org/tutorial/ The Python Tutorial] before you continue.
63 |
64 | * Beginner:
65 | * TutorialPage0 -- Installing python-csp, tool support
66 | * TutorialPage1 -- Creating and running processes
67 | * [http://code.google.com/p/python-csp/wiki/TutorialPage1#Larger_example:_a_basic_web_server Extended example:] web server
68 | * TutorialPage2 -- Composing processes with Par and Seq
69 | * [http://code.google.com/p/python-csp/wiki/TutorialPage2#A_larger_example:_Word_counts_on_a_whole_directory Extended example:] Parallel word count
70 | * TutorialPage3 -- Communicating between processes with channels
71 | * [http://code.google.com/p/python-csp/wiki/TutorialPage3#A_larger_example:_? Extended example:] Mandelbrot generator
72 | * TutorialPage4 -- Stopping python-csp programs by poisoning channels
73 | * [http://code.google.com/p/python-csp/wiki/TutorialPage4#A_larger_example:_? Extended example:] TODO
74 | * TutorialPage5 -- Choosing between channel reads with Alt
75 | * [http://code.google.com/p/python-csp/wiki/TutorialPage5#A_larger_example:_? Extended example:] TODO
76 |
77 | * Intermediate:
78 | * TutorialPage6 -- Using different channel types
79 | * TutorialPage7 -- Using built-in processes
80 | * [http://code.google.com/p/python-csp/wiki/TutorialPage7#A_larger_example:_? Extended example:] software oscilloscope
81 | * TutorialPage8 -- Design patterns for python-csp programs
82 | * [http://code.google.com/p/python-csp/wiki/TutorialPage8#A_larger_example:_? Extended example:] TODO
83 |
84 | * Advanced:
85 | * TutorialPage9 -- Debugging python-csp programs with extra tool support
86 | * TutorialPage10 -- Reactive (or dataflow) programming with python-csp
--------------------------------------------------------------------------------
/rst/TutorialPage0.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp Tutorial Part 0
2 | #labels Phase-Support,Tutorial
3 |
4 |
5 |
6 | = Downloading and installing python-csp =
7 |
8 | At the moment the only way to obtain python-csp is via the Mercurial
9 | repository, this will change in the next few weeks as we head towards
10 | a full release. Also, python-csp is currently only available on Linux
11 | (although it will likely work for other UNIX variants).
12 |
13 | So, for now to obtain python-csp you need to have
14 | [http://mercurial.selenic.com/ Mercurial] installed, then type this at
15 | the command line to download ("pull" in Mercurial parlance) python-csp
16 | into a new directory called python-csp:
17 |
18 |
19 | {{{
20 | $ hg clone https://python-csp.googlecode.com/hg/ python-csp
21 | }}}
22 |
23 | Then install python-csp using the usual Python setup protocol:
24 |
25 | {{{
26 | $ cd python-csp
27 | $ sudo python setup.py install
28 | }}}
29 |
30 | = Tool support =
31 |
32 | "Vanilla" Python comes with an interpreter shell that gives you access to the programming language, built in help, and so on. python-csp comes with a variant of this shell with some additions. To start the shell just type:
33 |
34 | {{{
35 | $ python-csp
36 | }}}
37 |
38 | at the command line, or, if you are using Gnome, you should have a python-csp entry on your *Applications -> Programming* menu.
39 |
40 | === Command history ===
41 |
42 | Unlike the ordinary Python shell, by default the python-csp shell has command history enabled. This means that you can press the "up" or "down" arrows on your keyboard to scroll through the code you have entered into the shell, saving you valuable typing time.
43 |
44 |
45 | === python-csp specific help ===
46 |
47 | You can use Python's `help()` function to examine any module, class, function or variable that comes with python-csp, just like you can with any other library. However, the python-csp shell comes with a set of specific documentation that you can access via the `info` command.
48 |
49 |
50 | You can start by typing `info csp` to get general information about the python-csp library, or you can ask for `info` on a specific topic to drill down into the details. Note that `info` is a command and not a function, so you say `info csp` not `info(csp)`.
51 |
52 | Here's an example python-csp shell session:
53 |
54 | {{{
55 | $ python-csp
56 |
57 | CSP Python (c) 2008. Licensed under the GPL(v2).
58 | Type "info csp" for more information.
59 | Press Ctrl-C to close the CSP channel server.
60 |
61 | >>> info
62 |
63 | *** python-csp: general info ***
64 |
65 | python-csp is an implementation of Hoare's Communicating Sequential
66 | Processes in Python. For specific info on any aspect of CSP, use the
67 | following:
68 |
69 | For info on Skip, type: info skip
70 | For info on channels, type: info channel
71 | For info on Alternative, type: info alt
72 | For info on CSPServer, type: info server
73 | For info on poisoning, type: info poison
74 | For info on built-ins, type: info builtin
75 | For info on Sequence, type: info seq
76 | For info on Timer, type: info timer
77 | For info on Parallel, type: info par
78 | For info on processes, type: info process
79 |
80 | >>>
81 |
82 | }}}
83 |
84 | = Next in the tutorial ... =
85 |
86 | TutorialPage1 -- Creating and running processes
--------------------------------------------------------------------------------
/rst/TutorialPage2.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp Tutorial Part 2
2 | #labels Phase-Support,Tutorial
3 |
4 |
5 |
6 | = Process algebra =
7 |
8 | Just like there are different ways to combine numbers with operators
9 | such as `+`, `-`, `*` and `/`, there are different ways to combine
10 | python-csp processes. Primarily, we can run one process to completion and
11 |
12 |
13 | = Running processes in sequence =
14 |
15 | There are two ways to run processes in sequence. Firstly, given two
16 | (or more) processes you can sequence them with the `>` operator, like this:
17 |
18 | {{{
19 | >>> @process
20 | ... def foo(n):
21 | ... import time
22 | ... print n
23 | ... time.sleep(0.2)
24 | ... print n + 1
25 | ... time.sleep(0.2)
26 | ... print n + 2
27 | ...
28 | >>> foo(100) > foo(200) > foo(300)
29 | n: 100
30 | n: 101
31 | n: 102
32 | n: 200
33 | n: 201
34 | n: 202
35 | n: 300
36 | n: 301
37 | n: 302
38 |
39 | >>>
40 | >>>
41 | }}}
42 |
43 | Secondly, you can create a `Seq` object which is a sort of CSP process
44 | and start that process manually:
45 |
46 | {{{
47 | >>> s = Seq(foo(400), foo(500), foo(600))
48 | >>> s.start()
49 | n: 400
50 | n: 401
51 | n: 402
52 | n: 500
53 | n: 501
54 | n: 502
55 | n: 600
56 | n: 601
57 | n: 602
58 | >>>
59 | }}}
60 |
61 |
62 |
63 | = Parallel processes =
64 |
65 | There are two ways to run processes in parallel. Firstly, given two
66 | (or more) processes you can parallelize them with the `//` operator, like this:
67 |
68 | {{{
69 | >>> @process
70 | ... def foo(n):
71 | ... import time
72 | ... print n
73 | ... time.sleep(0.2)
74 | ... print n + 1
75 | ... time.sleep(0.2)
76 | ... print n + 2
77 | ...
78 | >>> foo(100) // (foo(200), foo(300))
79 | n: 100
80 | n: 200
81 | n: 300
82 | n: 101
83 | n: 201
84 | n: 301
85 | n: 102
86 | n: 202
87 | n: 302
88 |
89 | >>>
90 | }}}
91 |
92 | Notice that the // operator is a synthetic sugar that takes a CSPProcess on the left hand side and a sequence of processes on the right hand side.
93 |
94 | Alternatively, you can create a `Par` object which is a sort of CSP
95 | process and start that process manually:
96 |
97 | {{{
98 | >>> p = Par(foo(100), foo(200), foo(300))
99 | >>> p.start()
100 | n: 100
101 | n: 200
102 | n: 300
103 | n: 101
104 | n: 201
105 | n: 301
106 | n: 102
107 | n: 202
108 | n: 302
109 | >>>
110 | }}}
111 |
112 |
113 | = Repeated processes =
114 |
115 | If you want to a single process to run to completion many times, you can use the `*` operator:
116 |
117 | {{{
118 | >>> @process
119 | ... def foo():
120 | ... print 'hello world!'
121 | ...
122 | >>> foo() * 3
123 | hello world!
124 | hello world!
125 | hello world!
126 | >>>
127 | }}}
128 |
129 |
130 | You can also say
131 |
132 | {{{
133 | 3 * foo()
134 | }}}
135 |
136 | with the same effect.
137 |
138 | = A larger example: Word counts on a whole directory =
139 |
140 | In this example we will use `Par` to concurrently process all files in
141 | a directory and print out their word counts. We just need two sorts of
142 | processes for this, one which counts all the words in a single file,
143 | and another which finds all the files in a given directory and runs
144 | the word count process on them. The first process is simple:
145 |
146 | {{{
147 | @process
148 | def word_count(filename):
149 | fd = file(filename)
150 | words = [line.split() for line in fd]
151 | fd.close()
152 | print '%s contains %i words.' % (filename, len(words))
153 | }}}
154 |
155 |
156 | The second process is a bit more complicated. We want to know about
157 | every file in the given directory, but we don't want to know about
158 | directories and other things that aren't really files, so we need a
159 | bit of logic to do that. After that, we just need to use `Par` to
160 | process all our files in parallel:
161 |
162 | {{{
163 | @process
164 | def directory_count(path):
165 | import glob
166 | import os.path
167 | import sys
168 | # Test if directory exists
169 | if not os.path.exists(path):
170 | print '%s does not exist. Exiting.' % path
171 | sys.exit(1)
172 | # Get all filenames in directory
173 | paths = glob.glob(path + '/*')
174 | files = [path for path in paths if not os.path.isdir(path) and os.path.isfile(path)]
175 | procs = [word_count(fd) for fd in files]
176 | Par(*procs).start()
177 | }}}
178 |
179 |
180 | This program gives output like this:
181 |
182 | {{{
183 | $ python tutorial/part02/filecount.py .
184 | ./setup.py contains 37 words.
185 | ./MANIFEST.in contains 6 words.
186 | ./maketags.sh contains 3 words.
187 | ./setup.cfg contains 3 words.
188 | ./LICENSE contains 339 words.
189 | ./ChangeLog contains 40 words.
190 | ./Makefile contains 91 words.
191 | ./make.bat contains 112 words.
192 | ./TAGS contains 954 words.
193 | ./BUCKETS.pdf contains 616 words.
194 | ./README.html contains 92 words.
195 | ./README contains 72 words.
196 | $
197 | }}}
198 |
199 | This is a rather simplistic example for a couple of reasons. In most
200 | concurrent or parallel programming you really need processes to pass
201 | data between themselves. For example, a more sophisticated version of
202 | our program would have `word_count` processes and pass their word
203 | counts to a separate process which would print everything to the
204 | console. This relies on the operating system to print each line of our
205 | output separately, even though the processes who are printing are
206 | running concurrently and might interfere with each other. We will
207 | learn how to pass messages between processes and improve this code in
208 | TutorialPage3.
209 |
210 |
211 | = Exercises =
212 |
213 | WRITEME!
214 |
215 |
216 | = Next in the tutorial ... =
217 |
218 | TutorialPage3 -- Communicating between processes with channels
--------------------------------------------------------------------------------
/rst/TutorialPage4.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp Tutorial Part 4
2 | #labels Phase-Support,Tutorial
3 |
4 |
5 |
6 | = Poisoning channels and terminating processes =
7 |
8 | A set of communicating processes can be terminated by "poisoning" any
9 | of the channels used by those processes. This can be achieved by
10 | calling the `poison()` method on any channel. For example:
11 |
12 | {{{
13 | >>> import time
14 | >>> import random
15 | >>> @process
16 | ... def send5(cout):
17 | ... for i in xrange(5):
18 | ... print 'send5 sending:', i
19 | ... cout.write(i)
20 | ... time.sleep(random.random() * 5)
21 | ... return
22 | ...
23 | >>> @process
24 | ... def recv(cin):
25 | ... for i in xrange(5):
26 | ... data = cin.read()
27 | ... print 'recv got:', data
28 | ... time.sleep(random.random() * 5)
29 | ... return
30 | ...
31 | >>> @process
32 | ... def interrupt(chan):
33 | ... time.sleep(random.random() * 7)
34 | ... print 'Poisoning channel:', chan.name
35 | ... chan.poison()
36 | ... return
37 | ...
38 | >>> doomed = Channel()
39 | >>> Par(send5(doomed), recv(doomed), interrupt(doomed)).start()
40 | send5 sending: 0
41 | recv got: 0
42 | send5 sending: 1
43 | recv got: 1
44 | send5 sending: 2
45 | recv got: 2
46 | send5 sending: 3
47 | recv got: 3
48 | Poisoning channel: 5c906e38-5559-11df-8503-002421449824
49 | send5 sending: 4
50 | >>>
51 | }}}
52 |
53 | = A larger example: =
54 | The second example tries to demonstrate the poisoning of all channels that are related to primary channel. In this case merchant is watching what customers are going to send and merchant's wife is watching what customer's children are going to send.
55 |
56 | {{{
57 | import time
58 | import random
59 | @process
60 | def customer_child(cchildout, n):
61 | for i in xrange(3):
62 | print "Customer's "+str(n)+" child sending "+str(i)
63 | cchildout.write(i)
64 | time.sleep(random.random() * 3)
65 | return
66 |
67 | @process
68 | def customer(cparentout, cchildout, n):
69 | for i in xrange(5):
70 | print 'Customer '+str(n)+" sending "+str(i)
71 | Par(customer_child(cchildout, n)).start()
72 | cparentout.write(i)
73 | time.sleep(random.random() * 5)
74 | return
75 |
76 | @process
77 | def merchant(cin):
78 | for i in xrange(15):
79 | data = cin.read()
80 | print 'Merchant got:', data
81 | time.sleep(random.random() * 5)
82 | return
83 |
84 | @process
85 | def merchantswife(cin):
86 | for i in xrange(15):
87 | data = cin.read()
88 | print "Merchant's wife got: ", data
89 | time.sleep(random.random() * 4)
90 | return
91 |
92 | @process
93 | def terminator(chan):
94 | time.sleep(10)
95 | print 'Terminator is killing channel:', chan.name
96 | chan.poison()
97 | return
98 |
99 | doomed = Channel()
100 | doomed_children = Channel()
101 | Par(customer(doomed, doomed_children, 1),\
102 | merchant(doomed), \
103 | merchantswife(doomed_children), \
104 | customer(doomed, doomed_children, 2), \
105 | customer(doomed, doomed_children, 3), \
106 | terminator(doomed)).start()
107 | }}}
108 | = Exercises =
109 |
110 | Writeme!
111 |
112 | = Next in the tutorial ... =
113 |
114 | TutorialPage5 -- Choosing between channel reads with Alt
--------------------------------------------------------------------------------
/rst/TutorialPage5.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp Tutorial Part 5
2 | #labels Phase-Support,Tutorial
3 |
4 |
5 |
6 | = Choosing between channel reads with Alt =
7 |
8 | python-csp process will often have access to several different channels, or other guard types such as timer guards, and will have to choose one of them to read from. For example, in a producer/consumer or worker/farmer model, many producer or worker processes will be writing values to channels and one consumer or farmer process will be aggregating them in some way. It would be inefficient for the consumer or farmer to read from each channel in turn, as some channels might take longer than others. Instead, python-csp provides support for ALTing (or ALTernating), which enables a process to read from the first channel (or timer, or other guard) in a list to become ready.
9 |
10 | == Using the choice operator ==
11 |
12 | The simplest way to choose between channels (or other guards) is to use choice operator: `|`, as in the example below:
13 |
14 | {{{
15 | >>> @process
16 | ... def send_msg(chan, msg):
17 | ... chan.write(msg)
18 | ...
19 | >>> @process
20 | ... def choice(chan1, chan2):
21 | ... # Choice chooses a channel on which to call read()
22 | ... print chan1 | chan2
23 | ... print chan1 | chan2
24 | ...
25 | >>> c1, c2 = Channel(), Channel()
26 | >>> choice(c1, c2) // (send_msg(c1, 'yes'), send_msg(c2, 'no'))
27 | yes
28 | no
29 |
30 | >>>
31 | }}}
32 |
33 | == Alt objects ==
34 |
35 | Secondly, you can create an `Alt` object explicitly, and call its `select()` method to perform a channel read on the next available channel. If more than one channel is available to read from, then an available channel is chosen at random (for this reason, ALTing is sometimes called "non-deterministic choice":
36 |
37 | {{{
38 | >>> @process
39 | ... def send_msg(chan, msg):
40 | ... chan.write(msg)
41 | ...
42 | >>> @process
43 | ... def alt_example(chan1, chan2):
44 | ... alt = Alt(chan1, chan2)
45 | ... print alt.select()
46 | ... print alt.select()
47 | ...
48 | >>> c1, c2 = Channel(), Channel()
49 | >>> Par(send_msg(c1, 'yes'), send_msg(c2, 'no'), alt_example(c1, c2)).start()
50 | yes
51 | no
52 | >>>
53 | }}}
54 |
55 | == Alternatives to the select method ==
56 |
57 | In addition to the `select()` method, which chooses an available guard at random, `Alt` provides two similar methods, `fair_select()` and `pri_select()`. `fair_select()` will choose not to select the previously selected guard, unless it is the only guard available. This ensures that no guard will be starved twice in a row. `pri_select()` will select available channels in the order in which they were passed to the `Alt()` constructor, giving a simple implementation of guard priority.
58 |
59 | Lastly, `Alt()` can be used with the repetition operator `*` to create a generator:
60 |
61 | {{{
62 | >>> @process
63 | ... def send_msg(chan, msg):
64 | ... chan.write(msg)
65 | ...
66 | >>> @process
67 | ... def gen_example(chan1, chan2):
68 | ... gen = Alt(chan1, chan2) * 2
69 | ... print gen.next()
70 | ... print gen.next()
71 | ...
72 | >>> c1, c2 = Channel(), Channel()
73 | >>> Par(send_msg(c1, 'yes'), send_msg(c2, 'no'), gen_example(c1, c2)).start()
74 | yes
75 | no
76 | >>>
77 | }}}
78 |
79 |
80 | = Fixing the Mandelbrot generator =
81 |
82 | In TutorialPage3 we described a producer / consumer architecture for
83 | generating pictures of the Mandelbrot set. There, we used a crude
84 | `for` loop for the consumer process to iterate over input channels and
85 | read from them. We can now improve this code and, usint `Alt`, make
86 | sure that channel reads are serviced when the reads are ready to
87 | complete:
88 |
89 |
90 | {{{
91 | @process
92 | def consume(size, cins):
93 | # Set-up PyGame.
94 | pixmap = ... # Blit buffer.
95 | gen = len(cins) * Alt(*cins)
96 | for i in range(len(cins)):
97 | xcoord, column = gen.next()
98 | # Update column of blit buffer
99 | pixmap[xcoord] = column
100 | # Update image on screen.
101 | }}}
102 |
103 |
104 |
105 | = A larger example: ? =
106 |
107 | Writeme!
108 |
109 | = Exercises =
110 |
111 | Writeme!
112 |
113 | = Next in the tutorial ... =
114 |
115 | TutorialPage6 -- Using different channel types
--------------------------------------------------------------------------------
/rst/TutorialPage7.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp Tutorial Part 7
2 | #labels Phase-Support,Tutorial
3 |
4 |
5 |
6 | = Builtin guards =
7 |
8 | So far, we have only used channels to `read()` and `write()` from/to
9 | and pass to `Alt` objects. Other objects can be used in these ways
10 | too, and in CSP these sorts of objects are all called _guards_. The
11 | modules `csp.guards` and `csp.builtins` contain a number of basic
12 | guards and processes which can be used as building blocks for larger
13 | programs. These are largely based on a similar library in JCSP called
14 | "plugNplay" and can be useful for quickly bootstraping programs.
15 |
16 | It is best to import the modules and look through their documentation,
17 | but this tutorial page covers a few of the more useful or unusual
18 | builtins with some examples.
19 |
20 |
21 | == Timer ==
22 |
23 | Guard which only commits to synchronisation when a timer has
24 | expired. A `Timer` can also be used to _sleep_ a process without
25 | importing the Python `time` module. For example:
26 |
27 | {{{
28 | from csp.builtins import Timer
29 | from csp.csp import *
30 |
31 | @process
32 | def foobar():
33 | timer = Timer()
34 | print '1, 2, 3, 4, ...'
35 | timer.sleep(2) # 2 seconds.
36 | print '5'
37 | }}}
38 |
39 |
40 | To use a timer to execute code after a specified amount of time you
41 | need to set it's `alarm` to trigger after a number of seconds and then
42 | pass the timer to an `Alt`. The `Alt` will be able to select the timer
43 | when it's alarm has triggered, like this:
44 |
45 | {{{
46 | from csp.builtins import Timer
47 | from csp.csp import *
48 |
49 | @process
50 | def foobar():
51 | timer = Timer()
52 | alt = Alt(timer)
53 | timer.set_alarm(5)
54 | alt.select() # Wait 5 seconds here.
55 | print '5 seconds is up!'
56 | }}}
57 |
58 |
59 | == Skip ==
60 |
61 | Guard which will always return `True`. Useful in `Alt`s where the
62 | programmer wants to ensure that `Alt.select` will always synchronise
63 | with at least one guard.
64 |
65 |
66 | = Builtin processes =
67 |
68 |
69 |
70 |
71 | == Documentation for (some) builtins ==
72 |
73 |
74 | == Skip ==
75 |
76 | As well as being a guard, Skip can be used as a process which does
77 | nothing. Think of it as the CSP equivalent of `None`:
78 |
79 | {{{
80 | >>> Skip().start()
81 | >>>
82 | }}}
83 |
84 |
85 | === Blackhole ===
86 | Read values from `cin` and do nothing with them.
87 |
88 |
89 | === Clock ===
90 | Send `None` object down output channel every `resolution` seconds.
91 |
92 |
93 | === Generate ===
94 |
95 | Generate successive (+ve) `int`s and write to `cout`. There is a
96 | similar process with the signature `GenerateFloats(outchan,
97 | epsilon=0.1)` which generates `float`s rather than `int`s. The
98 | argument `epsilon` says how far apart each floating point number
99 | should be. So the call `GenerateFloats(outchan, epsilon=0.1)' will
100 | write the numbers 0.1, 0.2, 0.3, ... down the channel `outchan`.
101 |
102 |
103 | === Mux2 ===
104 |
105 | Mux2 provides a fair multiplex between two input channels.
106 |
107 | === Printer ===
108 |
109 | Print all values read from `cin` to standard out or `out`.
110 |
111 | === Zeroes ===
112 |
113 | Writes out a stream of zeroes.
114 |
115 |
116 | = Larger examlple: a basic oscilloscope =
117 |
118 | http://python-csp.googlecode.com/hg/tutorial/part07/Oscilloscope.png
119 |
120 | The full code for the oscilloscope can be found here: http://python-csp.googlecode.com/hg/tutorial/part07/oscilloscope.py . You will also need the traces code, here http://python-csp.googlecode.com/hg/tutorial/part07/traces.py .
121 |
122 |
123 |
124 | = Next in the tutorial ... =
125 |
126 | TutorialPage8 -- Design patterns for python-csp programs
--------------------------------------------------------------------------------
/rst/TutorialPage8.wiki:
--------------------------------------------------------------------------------
1 | #summary python-csp Tutorial Part 8
2 | #labels Phase-Support,Tutorial
3 |
4 |
5 |
6 | = Design patterns in python-csp =
7 |
8 | == Client-server pattern ==
9 |
10 | === Client-server example ===
11 |
12 |
13 | == Token ring pattern ==
14 |
15 | === Token ring example ===
16 |
17 | == Reactive programming pattern ==
18 |
19 | === Reactive programming example ===
20 |
--------------------------------------------------------------------------------
/rst/builtins.rst:
--------------------------------------------------------------------------------
1 | Pre-built proceses
2 | ==================
3 |
4 | .. automodule:: csp.builtins
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/rst/csp.rst:
--------------------------------------------------------------------------------
1 | Core CSP library.
2 | =================
3 |
4 | .. automodule:: csp.csp
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/rst/guards.rst:
--------------------------------------------------------------------------------
1 | Prebuilt synchronisation primitives.
2 | ====================================
3 |
4 | .. automodule:: csp.guards
5 | :members:
6 |
7 | ..
8 |
9 |
10 | * :ref:`genindex`
11 | * :ref:`modindex`
12 | * :ref:`search`
13 |
14 |
--------------------------------------------------------------------------------
/rst/index.rst:
--------------------------------------------------------------------------------
1 | .. python-csp documentation master file, created by
2 | sphinx-quickstart on Sat Apr 10 00:03:15 2010.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to python-csp's documentation!
7 | ======================================
8 |
9 | Contents:
10 |
11 | .. toctree::
12 | :maxdepth: 2
13 |
14 | csp.rst
15 | builtins.rst
16 | guards.rst
17 | patterns.rst
18 | mandelbrot.rst
19 |
20 |
21 | ..
22 |
23 | Indices and tables
24 | ==================
25 |
26 | * :ref:`genindex`
27 | * :ref:`modindex`
28 | * :ref:`search`
29 |
30 |
--------------------------------------------------------------------------------
/rst/mandelbrot.rst:
--------------------------------------------------------------------------------
1 | Mandelbrot example
2 | ==================
3 |
4 | .. automodule:: mandelbrot
5 | :members:
6 |
7 | ..
8 |
9 | * :ref:`genindex`
10 | * :ref:`modindex`
11 | * :ref:`search`
12 |
13 |
--------------------------------------------------------------------------------
/rst/patterns.rst:
--------------------------------------------------------------------------------
1 | Design patterns for automatically wiring process graphs
2 | =======================================================
3 |
4 | .. automodule:: csp.patterns
5 | :members:
6 |
7 | ..
8 |
9 |
10 | * :ref:`genindex`
11 | * :ref:`modindex`
12 | * :ref:`search`
13 |
14 |
--------------------------------------------------------------------------------
/scripts/cspdb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Debugger for the pyyhon-csp library.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | __author__ = 'Sarah Mount '
23 | __date__ = 'May 2010'
24 |
25 | import sys
26 |
27 | import csp.tracer.tracer as tracer
28 |
29 | from optparse import OptionParser
30 |
31 | parser = OptionParser()
32 |
33 | parser.add_option('-p', '--prog', dest='program',
34 | action='store',
35 | help='Program to be debugged')
36 |
37 | parser.add_option('-a', '--all', dest='all',
38 | action='store_true',
39 | help='Provide all available debugging information')
40 |
41 | parser.add_option('-m', '--model', dest='model',
42 | action='store_true',
43 | help='Provide a CSP_M model of PROGRAM, suitable for use with the FDR2 model checker')
44 |
45 | parser.add_option('-g', '--graph', dest='graph',
46 | action='store_true',
47 | help='Provide (as a PNG) a graph of the processes and guards created by PROGRAM')
48 |
49 | parser.add_option('-t', '--trace', dest='trace',
50 | action='store_true',
51 | help='Provide a Hoare-style CSP trace of PROGRAM')
52 |
53 | parser.add_option('-v', '--vcr', dest='vcr',
54 | action='store_true',
55 | help='Provide a view-centric reasoning trace of PROGRAM')
56 |
57 | parser.add_option('-s', '--struct', dest='struct',
58 | action='store_true',
59 | help='Provide a structural trace of PROGRAM')
60 |
61 |
62 | def create_icode():
63 | """Create an ICODE model of the given program.
64 | """
65 | raise NotImplementedError('ICODE models not yet implemented')
66 |
67 |
68 | def create_model(icode):
69 | """Create a CSP_M model of the given program
70 | """
71 | raise NotImplementedError('CSP_M models not yet implemented')
72 |
73 |
74 | def create_graph(icode):
75 | """Create a process graph of the given program
76 | """
77 | raise NotImplementedError('Process graphs not yet implemented')
78 |
79 |
80 | def create_trace(icode):
81 | """Create an CSP trace of the given program.
82 | """
83 | raise NotImplementedError('CSP traces not yet implemented')
84 |
85 |
86 | def create_vcr(icode):
87 | """Create an VCR trace of the given program.
88 | """
89 | raise NotImplementedError('VCR traces not yet implemented')
90 |
91 |
92 | def create_struct(icode):
93 | """Create a structural trace of the given program.
94 | """
95 | raise NotImplementedError('ICODE models not yet implemented')
96 |
97 |
98 | if __name__ == '__main__':
99 | (options, args) = parser.parse_args()
100 |
101 | if options.program:
102 | with tracer.csptrace():
103 | exec(compile(open(options.program).read(), options.program, 'exec'))
104 | else:
105 | parser.print_help()
106 |
107 | if options.all:
108 | icode = create_icode()
109 | create_model(icode)
110 | create_graph(icode)
111 | create_trace(icode)
112 | create_vcr(icode)
113 | create_struct(icode)
114 | sys.exit()
115 |
116 | if options.model: create_model(icode)
117 | if options.graph: create_graph(icode)
118 | if options.trace: create_trace(icode)
119 | if options.vcr: create_vcr(icode)
120 | if options.struct: create_struct(icode)
121 |
122 |
--------------------------------------------------------------------------------
/scripts/csplint:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from optparse import OptionParser
4 |
5 | import csp.lint.lint
6 |
7 | import sys
8 |
9 | parser = OptionParser()
10 |
11 | parser.add_option('-l', '--list', dest='listall',
12 | action='store_true',
13 | help='List all error messages and exit')
14 |
15 | parser.add_option('-p', '--prog', dest='program',
16 | action='store',
17 | help='Program to be statically checked')
18 |
19 | parser.add_option('-x', '--exclude', dest='excluded',
20 | action='store',
21 | help='Comma-separated list of error codes to exclude.')
22 |
23 |
24 | if __name__ == '__main__':
25 | import exstatic.cspwarnings
26 |
27 | (options, args) = parser.parse_args()
28 |
29 | if options.listall:
30 | exstatic.cspwarnings.list_error_codes()
31 | sys.exit()
32 |
33 | # Deal with the list of excluded error codes, if used.
34 | ex_list = []
35 | if options.excluded:
36 | ex_list = options.excluded.strip().split(',')
37 |
38 | if options.program:
39 | csp.lint.lint.run(options.program, excluded=ex_list)
40 | else:
41 | parser.print_help()
42 |
43 |
--------------------------------------------------------------------------------
/scripts/python-csp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """Interactive interpreter for python-csp, with online help.
4 |
5 | Features:
6 | * CSP primitives are imported automatically.
7 | * History is saved between sessions in C{~/.csp-console-history}.
8 | * Tab-completion can be used to complete keywords or variables.
9 |
10 | Copyright (C) Sarah Mount, 2009.
11 |
12 | This program is free software; you can redistribute it and/or
13 | modify it under the terms of the GNU General Public License
14 | as published by the Free Software Foundation; either version 2
15 | of the License, or (at your option) any later version.
16 |
17 | This program is distributed in the hope that it will be useful,
18 | but WITHOUT ANY WARRANTY; without even the implied warranty of
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 | GNU General Public License for more details.
21 |
22 | You should have received a copy of the GNU General Public License
23 | along with this program; if not, write to the Free Software
24 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 | """
26 |
27 | try:
28 | import readline
29 | except ImportError:
30 | print("Module readline not available.")
31 | else:
32 | import rlcompleter
33 | readline.parse_and_bind("tab: complete")
34 |
35 | import atexit
36 | import code
37 | import os
38 | import sys
39 |
40 |
41 | __author__ = 'Sarah Mount '
42 | __date__ = 'December 2008'
43 |
44 |
45 | class _Printer(object):
46 | """Print documentation in twenty-line chunks.
47 |
48 | Based on a class of the same name from the site.py module.
49 | """
50 | MAXLINES = 20
51 | def __init__(self, documentation):
52 | self.__lines = documentation.split('\n')
53 | self.__linecnt = len(self.__lines)
54 |
55 | def __call__(self):
56 | prompt = '\n*** Hit Return for more, or q (and Return) to quit: '
57 | lineno = 0
58 | while True:
59 | try:
60 | for i in range(lineno, lineno + self.MAXLINES):
61 | print(self.__lines[i])
62 | except IndexError:
63 | break
64 | else:
65 | lineno += self.MAXLINES
66 | key = None
67 | while key not in ('', 'q', 'Q'):
68 | key = input(prompt)
69 | if key == 'q':
70 | break
71 | print()
72 |
73 |
74 | class TabSafeCompleter(rlcompleter.Completer):
75 | """Enable safe use of Tab for either tab completion or nested scope.
76 | """
77 | def complete(self, text, state):
78 | if text == '':
79 | return ['\t', None][state]
80 | else:
81 | return rlcompleter.Completer.complete(self, text, state)
82 |
83 |
84 | class CSPConsole(code.InteractiveConsole):
85 | """python-csp interactive console with REPL.
86 |
87 | Features:
88 | * CSP channel server is started automatically.
89 | * CSP primitives are imported automatically.
90 | * History is saved between sessions in C{~/.csp-console-history}.
91 | * Tab-completion can be used to complete keywords or variables.
92 | """
93 |
94 | # From the docs of the readline module.
95 | def __init__(self, locals=None, filename="",
96 | histfile=os.path.expanduser("~/.csp-console-history")):
97 | code.InteractiveConsole.__init__(self)
98 | self.init_history(histfile)
99 |
100 | def init_history(self, histfile):
101 | readline.parse_and_bind("tab: complete")
102 | delims = ' \t\n`!@#$%^&*()-=+[{]}\\|;:,<>?'
103 | readline.set_completer_delims(delims)
104 | readline.set_completer(TabSafeCompleter().complete)
105 | if hasattr(readline, "read_history_file"):
106 | try:
107 | readline.read_history_file(histfile)
108 | except IOError:
109 | pass
110 | atexit.register(self.save_history, histfile)
111 |
112 | def save_history(self, histfile):
113 | readline.write_history_file(histfile)
114 |
115 | def raw_input(self, *args):
116 | return code.InteractiveConsole.raw_input(self, *args)
117 |
118 |
119 | _ban = "\npython-csp (c) 2008. Licensed under the GPL(v2).\n\n"
120 |
121 |
122 | if __name__ == '__main__':
123 | c = CSPConsole(locals=locals())
124 | # Don't expect the csp types to be available in locals()
125 | c.push('from csp.csp import *')
126 | c.push('from csp.builtins import *')
127 | c.push('from csp.guards import *')
128 | c.interact(banner=_ban)
129 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [egg_info]
2 | tag_build = dev
3 | tag_svn_revision = true
4 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from setuptools import setup, find_packages
4 |
5 | version = '0.1'
6 |
7 | setup(name='python-csp',
8 | version=version,
9 | description="Communicating sequential processes for Python",
10 | long_description="""\
11 | python-csp adds communicating sequential processes to Python""",
12 | classifiers=["Intended Audience :: Developers",
13 | "License :: OSI Approved :: GNU General Public License (GPL)",
14 | "Programming Language :: Python",
15 | "Topic :: Software Development :: Libraries",
16 | "Topic :: System :: Distributed Computing"],
17 | keywords='concurrency multicore parallel',
18 | author='Sarah Mount',
19 | author_email='s.mount@wlv.ac.uk',
20 | url='http://code.google.com/p/python-csp/',
21 | license='GPL',
22 | packages=find_packages(exclude=['ez_setup', 'examples', 'tests',
23 | 'reactive', 'applications', 'benchmark',
24 | 'jythonsetup', 'logo', 'rst', 'scripts',
25 | 'test', 'tutorial']),
26 | include_package_data=True,
27 | zip_safe=True,
28 | scripts=['scripts/python-csp',
29 | 'scripts/csplint',
30 | 'scripts/cspdb'],
31 | install_requires=[
32 | # -*- Extra requirements: -*-
33 | ],
34 | entry_points="""
35 | # -*- Entry points: -*-
36 | """,
37 | )
38 |
--------------------------------------------------------------------------------
/test/test_contexts.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | """
4 | Test the CSP class, found in csp.csp and its context managers.
5 |
6 | TODO: Replace this with proper unit testing.
7 |
8 | Copyright (C) Sarah Mount, 2010.
9 |
10 | This program is free software; you can redistribute it and/or
11 | modify it under the terms of the GNU General Public License
12 | as published by the Free Software Foundation; either version 2
13 | of the License, or (at your option) any later version.
14 |
15 | This program is distributed in the hope that it will be useful,
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 | GNU General Public License for more details.
19 |
20 | You should have received a copy of the GNU General Public License
21 | along with this program. If not, see .
22 | """
23 |
24 | import sys
25 |
26 | sys.path.insert(0, "..")
27 |
28 | from csp.csp import CSP
29 |
30 |
31 | def printme(*args):
32 | print ' '.join(map(lambda x: str(x), args))
33 |
34 |
35 | def testme1():
36 | p = CSP()
37 | with p.par():
38 | p.process(printme, 1, 2, 3, 4, 5)
39 | p.process(printme, 6, 7, 7, 8, 9)
40 | p.process(printme, 2, 3, 6, 3, 2)
41 | p.start()
42 |
43 |
44 | def testme2():
45 | p = CSP()
46 | with p.seq():
47 | p.process(printme, 1, 2, 3)
48 | with p.par():
49 | p.process(printme, 1)
50 | p.process(printme, 2)
51 | p.process(printme, 3)
52 | p.process(printme, 5, 6, 7)
53 | p.start()
54 |
55 |
56 | if __name__ == '__main__':
57 | print 'Test 1'
58 | testme1()
59 | print 'Test 2'
60 | testme2()
61 |
62 |
--------------------------------------------------------------------------------
/test/test_forever.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Test the @forever process decorator which creates server processes.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 | import operator
23 | import os
24 | import sys
25 |
26 | from functools import reduce
27 |
28 | sys.path.insert(0, "..")
29 |
30 | from csp.csp import *
31 | from csp.builtins import Generate, Printer
32 |
33 |
34 | def test_builtins():
35 | channel, skip = Channel(), Skip()
36 | skip //= Generate(channel), Printer(channel)
37 |
38 |
39 | @forever
40 | def fact(outchan):
41 | """
42 | readset = flibble, foo
43 | writeset = outchan, foo
44 | """
45 | n = 1
46 | f = 1
47 | while True:
48 | if n == 1:
49 | outchan.write(1)
50 | else:
51 | f = reduce(operator.mul, list(range(1, n)))
52 | outchan.write(f)
53 | n += 1
54 | yield
55 |
56 | def test_fact():
57 | channel, skip = Channel(), Skip()
58 | skip //= fact(channel), Printer(channel)
59 |
60 | if __name__ == '__main__':
61 | # test_builtins()
62 | test_fact()
63 |
--------------------------------------------------------------------------------
/test/test_tracer.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Test the new python-csp tracer.
5 |
6 | Includes regular and server processes and ALTing.
7 | """
8 |
9 | __author__ = 'Sarah Mount '
10 | __date__ = 'May 2010'
11 |
12 | import sys
13 |
14 | sys.path.insert(0, "..")
15 |
16 | from csp.csp import *
17 | from csp.guards import Skip
18 |
19 | ch = Channel()
20 |
21 | @process
22 | def client(inchan):
23 | """
24 | readset = inchan
25 | writeset =
26 | """
27 | print(inchan.read())
28 | return
29 |
30 |
31 | @process
32 | def foo(outchan, msg):
33 | """
34 | readset =
35 | writeset = outchan
36 | """
37 | outchan.write(msg)
38 | return
39 |
40 |
41 | @process
42 | def alt3(inchan1, inchan2, inchan3):
43 | """
44 | readset = inchan1, inchan2, inchan3
45 | writeset =
46 | """
47 | alt = Alt(inchan1, inchan2, inchan3, Skip())
48 | selects = 0
49 | while selects < 3:
50 | val = alt.select()
51 | if val != 'Skip':
52 | selects += 1
53 | print(val)
54 | return
55 |
56 |
57 | @process
58 | def simple():
59 | print('SIMPLES')
60 | return
61 |
62 |
63 | @forever
64 | def server():
65 | while True:
66 | print('server process')
67 | yield
68 | return
69 |
70 |
71 | @forever
72 | def server_write(outchan):
73 | """
74 | readset =
75 | writeset = outchan
76 | """
77 | while True:
78 | outchan.write('Hello server')
79 | yield
80 | return
81 |
82 |
83 | @forever
84 | def server_read(inchan):
85 | """
86 | readset = inchan
87 | writeset =
88 | """
89 | while True:
90 | print(inchan.read())
91 | yield
92 | return
93 |
94 |
95 | if __name__ == '__main__':
96 | from csp.tracer.tracer import csptrace
97 | with csptrace():
98 | chan, skip = Channel(), Skip()
99 | skip //= foo(chan, 'hello world!'), client(chan)
100 | Par(foo(chan, 1243), client(chan)).start()
101 | chan1, chan2, chan3 = Channel(), Channel(), Channel()
102 | Par(foo(chan1, 1),
103 | foo(chan2, 2),
104 | foo(chan3, 3),
105 | alt3(chan1, chan2, chan3)).start()
106 | simple().start()
107 | server().start()
108 | chan_s, skip = Channel(), Skip()
109 | skip //= server_read(chan_s), server_write(chan_s)
110 |
111 |
--------------------------------------------------------------------------------
/test/testpar.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 |
5 | sys.path.insert(0, "..")
6 |
7 | from csp.csp import *
8 | from csp.builtins import Generate, Plus, Printer
9 |
10 | in1, in2, out = Channel(), Channel(), Channel()
11 |
12 | @process
13 | def foo():
14 | # Previously deadlocked
15 | Skip() // (Generate(in1), Generate(in2), Plus(in1, in2, out), Printer(out))
16 |
17 |
18 | # Infinite stream of ints (OK)
19 | #p = Skip()
20 | #p //= [Generate(out), Printer(out)]
21 |
22 | @process
23 | def bar():
24 | # Infinite stream of even ints (OK)
25 | Par(Generate(in1), Generate(in2), Plus(in1, in2, out), Printer(out)).start()
26 |
27 |
28 | #PAR //= [Generate(in1), Generate(in2), Plus(in1, in2, out), Printer(out)]
29 |
30 | if __name__ == '__main__':
31 | Generate(out) // (Printer(out),)
32 | #
33 | # bar().start()
34 | # foo().start()
35 |
--------------------------------------------------------------------------------
/test/testrep.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | sys.path.insert(0, "..")
4 |
5 | from csp.csp import *
6 | from csp.guards import Timer
7 |
8 | @process
9 | def hello():
10 | t = Timer()
11 | for i in range(5):
12 | print i
13 | t.sleep(1)
14 |
15 | if __name__ == '__main__':
16 | hello() * 3
17 | 2 * hello()
18 |
--------------------------------------------------------------------------------
/test/testsock.py:
--------------------------------------------------------------------------------
1 | import socket
2 |
3 | HOST = socket.gethostbyname(socket.gethostname())
4 |
5 | PORT = 8887
6 | data = 'flibble'
7 |
8 | # sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
9 |
10 | # # Connect to server and send data
11 | # sock.connect((HOST, PORT))
12 | # sock.send(data + "\n")
13 |
14 | # # Receive data from the server and shut down
15 | # received = sock.recv(1024)
16 | # sock.close()
17 |
18 |
19 |
20 | # SOCK_DGRAM is the socket type to use for UDP sockets
21 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
22 | sock.sendto(data + "\n", (HOST, PORT))
23 | received = sock.recv(1024)
24 |
25 | print("Sent: {0}".format(data))
26 | print("Received: {0}".format(received))
27 |
--------------------------------------------------------------------------------
/test/winder_bug/pi_python_python-csp_multiple_nested_deep.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- mode:python; coding:utf-8; -*-
3 |
4 | # Calculation of Pi using quadrature. Using the python-csp package by Sarah Mount.
5 | #
6 | # Copyright © 2009-10 Russel Winder
7 |
8 | import time
9 | import multiprocessing
10 |
11 | import sys
12 | sys.path.insert(0, "../..")
13 |
14 | from csp.csp import *
15 |
16 | def execute ( processCount ) :
17 | n = 10#0000000 # 100 times fewer due to speed issues.
18 | delta = 1.0 / n
19 | startTime = time.time ( )
20 | slice = n / processCount
21 | channels = [ ]
22 | @process
23 | def accumulator ( ) :
24 | """
25 | readset = channel
26 | writeset =
27 | """
28 | pi = 4.0 * sum ( [ channel.read ( ) for channel in channels ] ) * delta
29 | elapseTime = time.time ( ) - startTime
30 | print ( "==== Python CSP Multiple NestedDeep pi = " + str ( pi ) )
31 | print ( "==== Python CSP Multiple NestedDeep iteration count = " + str ( n ) )
32 | print ( "==== Python CSP Multiple NestedDeep elapse = " + str ( elapseTime ) )
33 | print ( "==== Python CSP Multiple NestedDeep process count = " + str ( processCount ) )
34 | print ( "==== Python CSP Multiple NestedDeep processor count = " + str ( multiprocessing.cpu_count ( ) ) )
35 | processes = [ ]
36 | for i in range ( 0 , processCount ) :
37 | channel = Channel ( )
38 | channels.append ( channel )
39 | @process
40 | def calculator ( channel ) :
41 | """
42 | readset =
43 | writeset = channel
44 | """
45 | sum = 0.0
46 | for j in range ( 1 + i * slice , ( i + 1 ) * slice ) :
47 | x = ( j - 0.5 ) * delta
48 | sum += 1.0 / ( 1.0 + x * x )
49 | channel.write ( sum )
50 | processes.append ( calculator (channels[i] ) )
51 | processes.append ( accumulator ( ) )
52 | Par ( *processes ).start ( )
53 |
54 | if __name__ == '__main__' :
55 | import gc
56 | gc.set_debug(True)
57 | execute ( 1 )
58 | print ( )
59 | execute ( 2 )
60 | print ( )
61 | execute ( 8 )
62 | print ( )
63 | execute ( 32 )
64 |
65 |
--------------------------------------------------------------------------------
/test/winder_bug/pi_python_python-csp_multiple_nested_shallow.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- mode:python; coding:utf-8; -*-
3 |
4 | # Calculation of Pi using quadrature. Using the python-csp package by Sarah Mount.
5 | #
6 | # Copyright © 2009-10 Russel Winder
7 |
8 | import time
9 | import multiprocessing
10 |
11 | import sys
12 | sys.path.insert(0, "../..")
13 |
14 | from csp.csp import *
15 |
16 | def execute ( processCount ) :
17 | n = 100000000 # 100 times fewer due to speed issues.
18 | delta = 1.0 / n
19 | startTime = time.time ( )
20 | sliceSize = n / processCount
21 | channels = [ ]
22 | @process
23 | def calculator ( channel , id ) :
24 | """
25 | readset =
26 | writeset = channel
27 | """
28 | sum = 0.0
29 | for i in range ( 1 + id * sliceSize , ( id + 1 ) * sliceSize + 1 ) :
30 | x = ( i - 0.5 ) * delta
31 | sum += 1.0 / ( 1.0 + x * x )
32 | channel.write ( sum )
33 | @process
34 | def accumulator ( ) :
35 | """
36 | readset = channel
37 | writeset =
38 | """
39 | pi = 4.0 * sum ( [ channel.read ( ) for channel in channels ] ) * delta
40 | elapseTime = time.time ( ) - startTime
41 | print ( "==== Python CSP Multiple NestedShallow pi = " + str ( pi ) )
42 | print ( "==== Python CSP Multiple NestedShallow iteration count = " + str ( n ) )
43 | print ( "==== Python CSP Multiple NestedShallow elapse = " + str ( elapseTime ) )
44 | print ( "==== Python CSP Multiple NestedShallow process count = " + str ( processCount ) )
45 | print ( "==== Python CSP Multiple NestedShallow processor count = " + str ( multiprocessing.cpu_count ( ) ) )
46 | processes = [ ]
47 | for i in range ( 0 , processCount ) :
48 | channel = Channel ( )
49 | channels.append ( channel )
50 | processes.append ( calculator ( channel , i ) )
51 | processes.append ( accumulator ( ) )
52 | Par ( *processes ).start ( )
53 |
54 | if __name__ == '__main__' :
55 | execute ( 1 )
56 | print ( )
57 | execute ( 2 )
58 | print ( )
59 | execute ( 8 )
60 | print ( )
61 | execute ( 32 )
62 |
--------------------------------------------------------------------------------
/test/winder_bug/pi_python_python-csp_multiple_separate.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- mode:python; coding:utf-8; -*-
3 |
4 | # Calculation of Pi using quadrature. Using the python-csp package by Sarah Mount.
5 | #
6 | # Copyright © 2009-10 Russel Winder
7 |
8 | import time
9 | import multiprocessing
10 |
11 | import sys
12 | sys.path.insert(0, "../..")
13 |
14 | from csp.csp import *
15 |
16 | @process
17 | def calculator ( channel , id , sliceSize , delta ) :
18 | """
19 | readset =
20 | writeset = channel
21 | """
22 | sum = 0.0
23 | for i in range ( 1 + id * sliceSize , ( id + 1 ) * sliceSize + 1 ) :
24 | x = ( i - 0.5 ) * delta
25 | sum += 1.0 / ( 1.0 + x * x )
26 | channel.write ( sum )
27 |
28 | @process
29 | def accumulator ( channels , n , delta , startTime , processCount ) :
30 | """
31 | readset = channels
32 | writeset =
33 | """
34 | pi = 4.0 * sum ( [ channel.read ( ) for channel in channels ] ) * delta
35 | elapseTime = time.time ( ) - startTime
36 | print ( "==== Python CSP Multiple pi = " + str ( pi ) )
37 | print ( "==== Python CSP Multiple iteration count = " + str ( n ) )
38 | print ( "==== Python CSP Multiple elapse = " + str ( elapseTime ) )
39 | print ( "==== Python CSP Multiple process count = " + str ( processCount ) )
40 | print ( "==== Python CSP Multiple processor count = " + str ( multiprocessing.cpu_count ( ) ) )
41 |
42 | def execute ( processCount ) :
43 | n = 100000000 # 10 times fewer due to speed issues.
44 | delta = 1.0 / n
45 | startTime = time.time ( )
46 | sliceSize = n / processCount
47 | channels = [ ]
48 | processes = [ ]
49 | for i in range ( 0 , processCount ) :
50 | channel = Channel ( )
51 | channels.append ( channel )
52 | processes.append ( calculator ( channel , i , sliceSize , delta ) )
53 | processes.append ( accumulator ( channels , n , delta , startTime , processCount ) )
54 | Par ( *processes ).start ( )
55 |
56 | if __name__ == '__main__' :
57 | execute ( 1 )
58 | print ( )
59 | execute ( 2 )
60 | print ( )
61 | execute ( 8 )
62 | print ( )
63 | execute ( 32 )
64 |
--------------------------------------------------------------------------------
/test/winder_bug/pi_python_python-csp_single_nested_deep.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- mode:python; coding:utf-8; -*-
3 |
4 | # Calculation of Pi using quadrature. Using the python-csp package by Sarah Mount.
5 | #
6 | # Copyright © 2009-10 Russel Winder
7 |
8 | import time
9 | import multiprocessing
10 |
11 | import sys
12 | sys.path.insert(0, "../..")
13 |
14 | from csp.csp import *
15 |
16 | def execute ( processCount ) :
17 | n = 10000000 # 100 times fewer due to speed issues.
18 | delta = 1.0 / n
19 | startTime = time.time ( )
20 | slice = n / processCount
21 | channel = Channel ( )
22 | @process
23 | def accumulator ( ) :
24 | """
25 | readset = channel
26 | writeset =
27 | """
28 | pi = 4.0 * sum ( [ channel.read ( ) for i in range ( 0 , processCount ) ] ) * delta
29 | elapseTime = time.time ( ) - startTime
30 | print ( "==== Python CSP Single NestedDeep pi = " + str ( pi ) )
31 | print ( "==== Python CSP Single NestedDeep iteration count = " + str ( n ) )
32 | print ( "==== Python CSP Single NestedDeep elapse = " + str ( elapseTime ) )
33 | print ( "==== Python CSP Single NestedDeep process count = " + str ( processCount ) )
34 | print ( "==== Python CSP Single NestedDeep processor count = " + str ( multiprocessing.cpu_count ( ) ) )
35 | processes = [ ]
36 | for i in range ( 0 , processCount ) :
37 | @process
38 | def calculator ( ) :
39 | """
40 | readset =
41 | writeset = channel
42 | """
43 | sum = 0.0
44 | for j in range ( 1 + i * slice , ( i + 1 ) * slice ) :
45 | x = ( j - 0.5 ) * delta
46 | sum += 1.0 / ( 1.0 + x * x )
47 | channel.write ( sum )
48 | processes.append ( calculator ( ) )
49 | processes.append ( accumulator ( ) )
50 | Par ( *processes ).start ( )
51 |
52 | if __name__ == '__main__' :
53 | execute ( 1 )
54 | print ( )
55 | execute ( 2 )
56 | print ( )
57 | execute ( 8 )
58 | print ( )
59 | execute ( 32 )
60 |
--------------------------------------------------------------------------------
/test/winder_bug/pi_python_python-csp_single_nested_shallow.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- mode:python; coding:utf-8; -*-
3 |
4 | # Calculation of Pi using quadrature. Using the python-csp package by Sarah Mount.
5 | #
6 | # Copyright © 2009-10 Russel Winder
7 |
8 | import time
9 | import multiprocessing
10 |
11 | import sys
12 | sys.path.insert(0, "../..")
13 |
14 | from csp.csp import *
15 |
16 | def execute ( processCount ) :
17 | n = 10000000 # 100 times fewer due to speed issues.
18 | delta = 1.0 / n
19 | startTime = time.time ( )
20 | sliceSize = n / processCount
21 | channel = Channel ( )
22 | @process
23 | def calculator ( id ) :
24 | """
25 | readset =
26 | writeset = channel
27 | """
28 | sum = 0.0
29 | for i in range ( 1 + id * sliceSize , ( id + 1 ) * sliceSize + 1 ) :
30 | x = ( i - 0.5 ) * delta
31 | sum += 1.0 / ( 1.0 + x * x )
32 | channel.write ( sum )
33 | @process
34 | def accumulator ( ) :
35 | """
36 | readset = channel
37 | writeset =
38 | """
39 | pi = 4.0 * sum ( [ channel.read ( ) for i in range ( 0 , processCount ) ] ) * delta
40 | elapseTime = time.time ( ) - startTime
41 | print ( "==== Python CSP Single NestedShallow pi = " + str ( pi ) )
42 | print ( "==== Python CSP Single NestedShallow iteration count = " + str ( n ) )
43 | print ( "==== Python CSP Single NestedShallow elapse = " + str ( elapseTime ) )
44 | print ( "==== Python CSP Single NestedShallow process count = " + str ( processCount ) )
45 | print ( "==== Python CSP Single NestedShallow processor count = " + str ( multiprocessing.cpu_count ( ) ) )
46 | processes = [ ]
47 | for i in range ( 0 , processCount ) : processes.append ( calculator ( i ) )
48 | processes.append ( accumulator ( ) )
49 | Par ( *processes ).start ( )
50 |
51 | if __name__ == '__main__' :
52 | execute ( 1 )
53 | print ( )
54 | execute ( 2 )
55 | print ( )
56 | execute ( 8 )
57 | print ( )
58 | execute ( 32 )
59 |
--------------------------------------------------------------------------------
/test/winder_bug/pi_python_python-csp_single_separate.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- mode:python; coding:utf-8; -*-
3 |
4 | # Calculation of Pi using quadrature. Using the python-csp package by Sarah Mount.
5 | #
6 | # Copyright © 2009-10 Russel Winder
7 |
8 | import time
9 | import multiprocessing
10 |
11 | import sys
12 | sys.path.insert(0, "../..")
13 |
14 | from csp.csp import *
15 |
16 | @process
17 | def calculator ( channel , id , sliceSize , delta ) :
18 | """
19 | readset =
20 | writeset = channel
21 | """
22 | sum = 0.0
23 | for i in range ( 1 + id * sliceSize , ( id + 1 ) * sliceSize + 1 ) :
24 | x = ( i - 0.5 ) * delta
25 | sum += 1.0 / ( 1.0 + x * x )
26 | channel.write ( sum )
27 |
28 | @process
29 | def accumulator ( channel , n , delta , startTime , processCount ) :
30 | """
31 | readset = channel
32 | writeset =
33 | """
34 | pi = 4.0 * sum ( [ channel.read ( ) for i in range ( 0 , processCount ) ] ) * delta
35 | elapseTime = time.time ( ) - startTime
36 | print ( "==== Python CSP Single pi = " + str ( pi ) )
37 | print ( "==== Python CSP Single iteration count = " + str ( n ) )
38 | print ( "==== Python CSP Single elapse = " + str ( elapseTime ) )
39 | print ( "==== Python CSP Single process count = " + str ( processCount ) )
40 | print ( "==== Python CSP Single processor count = " + str ( multiprocessing.cpu_count ( ) ) )
41 |
42 | def execute ( processCount ) :
43 | n = 100000000 # 10 times fewer due to speed issues.
44 | delta = 1.0 / n
45 | startTime = time.time ( )
46 | sliceSize = n / processCount
47 | channel = Channel ( )
48 | processes = [ ]
49 | for i in range ( 0 , processCount ) : processes.append ( calculator ( channel , i , sliceSize , delta ) )
50 | processes.append ( accumulator ( channel , n , delta , startTime , processCount ) )
51 | Par ( *processes ).start ( )
52 |
53 | if __name__ == '__main__' :
54 | execute ( 1 )
55 | print ( )
56 | execute ( 2 )
57 | print ( )
58 | execute ( 8 )
59 | print ( )
60 | execute ( 32 )
61 |
--------------------------------------------------------------------------------
/tutorial/README:
--------------------------------------------------------------------------------
1 |
2 | Please find documentation on
3 | http://code.google.com/p/python-csp/w/list
4 |
5 | Dependencies:
6 | * Numpy
7 | * pygame (imageext for saving plots)
8 |
--------------------------------------------------------------------------------
/tutorial/part01/webserver.py:
--------------------------------------------------------------------------------
1 | # Example program from Part 01 of the python-csp tutorial
2 |
3 | # Copyright (C) Sarah Mount, 2010.
4 |
5 | # This program is free software; you can redistribute it and/or
6 | # modify it under the terms of the GNU General Public License
7 | # as published by the Free Software Foundation; either version 2
8 | # of the License, or (at your option) any later version.
9 |
10 | # This program is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 |
15 | # You should have rceeived a copy of the GNU General Public License
16 | # along with this program. If not, see .
17 |
18 | import socket
19 | import time
20 |
21 | from csp.csp import *
22 |
23 |
24 | def response(code, reason, page):
25 | """Construct and return a single HTTP response.
26 |
27 | FIXME: Should read and return files from disk, not a static page.
28 | FIXME: Should handle other MIME types.
29 | """
30 | html = """
31 |
32 | %i %s
33 |
34 | %s
35 |
36 | Date: %s
37 |
38 |
39 | """ % (code, reason, page, time.ctime())
40 | template = """HTTP/1.0 %i %s
41 | Content-Type: text/html
42 | Content-Length: %i
43 |
44 |
45 | %s
46 | """ % (code, reason, len(html), html)
47 | return template
48 |
49 |
50 | @process
51 | def server(host, port):
52 | """Simple CSP based web server.
53 | """
54 | print('Running tutorial web-server on port {0}...'.format(port))
55 | print('Interrupt with CTRL-C')
56 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
57 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
58 | sock.bind((host, port))
59 | sock.listen(5)
60 | while True:
61 | conn_sock, conn_addr = sock.accept()
62 | request = conn_sock.recv(4096).strip()
63 | if request.startswith('GET'):
64 | handler_ok(request, conn_sock).start()
65 | else:
66 | handler_not_found(request, conn_sock).start()
67 |
68 |
69 | @process
70 | def handler_ok(request, conn_sock):
71 | """Handle a single HTTP 200 OK request.
72 | """
73 | page = 'My python-csp web server! '
74 | page += 'You asked for:
%s
' % request
75 | conn_sock.send(response(200, 'OK', page))
76 | conn_sock.shutdown(socket.SHUT_RDWR)
77 | conn_sock.close()
78 | return
79 |
80 |
81 | @process
82 | def handler_not_found(request, conn_sock):
83 | """Handle a single HTTP 404 Not Found request.
84 | """
85 | page = 'Cannot find your file '
86 | page += 'You asked for:
%s ' % request
87 | conn_sock.send(response(404, 'Not Found', page))
88 | conn_sock.shutdown(socket.SHUT_RDWR)
89 | conn_sock.close()
90 | return
91 |
92 |
93 | if __name__ == '__main__':
94 | host = ''
95 | port = 8888
96 | server(host, port).start()
97 |
98 |
--------------------------------------------------------------------------------
/tutorial/part02/filecount.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Count the words in every file in a given directory.
5 |
6 | Copyright (C) Sarah Mount, 2010.
7 |
8 | This program is free software; you can redistribute it and/or
9 | modify it under the terms of the GNU General Public License
10 | as published by the Free Software Foundation; either version 2
11 | of the License, or (at your option) any later version.
12 |
13 | This program is distributed in the hope that it will be useful,
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | GNU General Public License for more details.
17 |
18 | You should have rceeived a copy of the GNU General Public License
19 | along with this program. If not, see .
20 | """
21 |
22 |
23 | from csp.csp import *
24 |
25 |
26 | __author__ = 'Sarah Mount '
27 | __date__ = 'July 2010'
28 |
29 |
30 | @process
31 | def word_count(filename):
32 | fd = file(filename)
33 | words = [line.split() for line in fd]
34 | fd.close()
35 | print '%s contains %i words.' % (filename, len(words))
36 |
37 |
38 | @process
39 | def directory_count(path):
40 | import glob
41 | import os.path
42 | import sys
43 | # Test if directory exists
44 | if not os.path.exists(path):
45 | print '%s does not exist. Exiting.' % path
46 | sys.exit(1)
47 | # Get all filenames in directory
48 | paths = glob.glob(path + '/*')
49 | files = [path for path in paths if not os.path.isdir(path) and os.path.isfile(path)]
50 | procs = [word_count(fd) for fd in files]
51 | Par(*procs).start()
52 |
53 |
54 | if __name__ == '__main__':
55 | import sys
56 | if sys.argv <= 1:
57 | print 'You need to provide this script with a directory path. Exiting.'
58 | sys.exit(1)
59 | else:
60 | directory_count(sys.argv[1]).start()
61 |
62 |
--------------------------------------------------------------------------------
/tutorial/part04/shop.py:
--------------------------------------------------------------------------------
1 | from csp.csp import *
2 | import random, time
3 |
4 | @process
5 | def customer_child(cchildout, n):
6 | for i in xrange(3):
7 | print "Customer's "+str(n)+" child sending "+str(i)
8 | cchildout.write(i)
9 | time.sleep(random.random() * 3)
10 | return
11 |
12 | @process
13 | def customer(cparentout, cchildout, n):
14 | for i in xrange(5):
15 | #print 'customer ', n, ' sending: customer '+str(i)
16 | print 'Customer '+str(n)+" sending "+str(i)
17 | Par(customer_child(cchildout, n)).start()
18 | cparentout.write(i)
19 | time.sleep(random.random() * 5)
20 | return
21 |
22 | @process
23 | def merchant(cin):
24 | for i in xrange(15):
25 | data = cin.read()
26 | print 'Merchant got:', data
27 | time.sleep(random.random() * 5)
28 | return
29 |
30 | @process
31 | def merchantswife(cin):
32 | for i in xrange(15):
33 | data = cin.read()
34 | print "Merchant's wife got: ", data
35 | time.sleep(random.random() * 4)
36 | return
37 |
38 | @process
39 | def terminator(chan):
40 | time.sleep(10)
41 | print 'Terminator is killing channel:', chan.name
42 | chan.poison()
43 | return
44 |
45 | doomed = Channel()
46 | doomed_children = Channel()
47 | Par(customer(doomed, doomed_children, 1), merchant(doomed), merchantswife(doomed_children), customer(doomed, doomed_children, 2), customer(doomed, doomed_children, 3), terminator(doomed)).start()
48 | #send5(doomed) // (recv(doomed), send52(doomed), interrupt(doomed))
49 |
--------------------------------------------------------------------------------
/tutorial/part07/Oscilloscope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/tutorial/part07/Oscilloscope.png
--------------------------------------------------------------------------------
/tutorial/part07/oscilloscope.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | """
4 | Simple oscilloscope traces for python-csp.
5 | Requires Pygame.
6 |
7 | Features:
8 | * Press 's' to save an oscilloscope trace as a PNG.
9 | * Press UP and DOWN to scale the input more / less.
10 |
11 | Copyright (C) Sarah Mount, 2009.
12 |
13 | This program is free software; you can redistribute it and/or
14 | modify it under the terms of the GNU General Public License
15 | as published by the Free Software Foundation; either version 2
16 | of the License, or (at your option) any later version.
17 |
18 | This program is distributed in the hope that it will be useful,
19 | but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | GNU General Public License for more details.
22 |
23 | You should have rceeived a copy of the GNU General Public License
24 | along with this program. If not, see .
25 | """
26 |
27 |
28 | from csp.csp import *
29 |
30 | import copy
31 | import numpy
32 | import pygame
33 |
34 |
35 | __author__ = 'Sarah Mount '
36 | __date__ = 'November 2009'
37 | __version__ = '0.2'
38 |
39 |
40 | @forever
41 | def Oscilloscope(inchan, scale=80.0, _process=None):
42 | # Constants
43 | WIDTH, HEIGHT = 512, 256
44 | TRACE, GREY = (80, 255, 100), (110, 110, 110)
45 | caption = 'Oscilloscope'
46 | filename = caption + '.png'
47 | # Open window
48 | pygame.init()
49 | screen = pygame.display.set_mode((WIDTH, HEIGHT), 0)
50 | pygame.display.set_caption(caption)
51 | # Create a blank chart with vertical ticks, etc
52 | blank = numpy.zeros((WIDTH, HEIGHT, 3), dtype=numpy.int8)
53 | # Draw x-axis
54 | xaxis = HEIGHT // 2
55 | blank[::, xaxis] = GREY
56 | # Draw vertical ticks
57 | vticks = [-100, -50, +50, +100]
58 | for vtick in vticks: blank[::5, xaxis + vtick] = GREY # Horizontals
59 | blank[::50, ::5] = GREY # Verticals
60 | # Draw the 'blank' screen.
61 | pygame.surfarray.blit_array(screen, blank) # Blit the screen buffer
62 | pygame.display.flip() # Flip the double buffer
63 | # ydata stores data for the trace.
64 | ydata = [0.0 for i in range(WIDTH)] # assert len(ydata) <= WIDTH
65 | QUIT = False
66 | while not QUIT:
67 | pixels = copy.copy(blank)
68 | ydata.append(inchan.read() * scale)
69 | ydata.pop(0)
70 | for x in range(WIDTH):
71 | try: pixels[x][xaxis - int(ydata[x])] = TRACE
72 | except: pass
73 | pygame.surfarray.blit_array(screen, pixels) # Blit the screen buffer
74 | pygame.display.flip() # Flip the double buffer
75 | #pygame.display.update(0, xaxis-100, WIDTH, 201) # Flip the double buffer
76 | del pixels # Use constant space.
77 | for event in pygame.event.get():
78 | if event.type == pygame.QUIT \
79 | or event.type == pygame.KEYDOWN and event.key == pygame.K_q:
80 | QUIT = True
81 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
82 | pygame.image.save(screen, filename)
83 | print('Saving oscope image in: ' + str ( filename ) )
84 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
85 | scale += 10.0
86 | print('Oscilloscope scaling by %f' % scale)
87 | elif event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
88 | if scale - 10.0 > 0.0: scale -= 10.0
89 | print('Oscilloscope scaling by %f' % scale)
90 | yield
91 | inchan.poison()
92 | pygame.display.quit()
93 | return
94 |
95 |
96 | if __name__ == '__main__':
97 | print('For this tutorial run traces.py')
98 |
--------------------------------------------------------------------------------
/tutorial/part07/traces.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | #
4 | # Example oscilloscope traces.
5 | #
6 |
7 | import sys
8 | from csp.csp import *
9 | from csp.builtins import Sin, Cos, GenerateFloats, Mux2, Delta2
10 | from oscilloscope import Oscilloscope
11 |
12 |
13 | @forever
14 | def Random(outchan):
15 | """Random process.
16 |
17 | Generates random data and writes it to outchan.
18 | """
19 | import random
20 | while True:
21 | outchan.write(random.random())
22 | yield
23 | return
24 |
25 |
26 | def trace_random():
27 | """Test the Oscilloscope with random data.
28 | """
29 | channel = Channel()
30 | par = Par(Random(channel), Oscilloscope(channel))
31 | par.start()
32 | return
33 |
34 |
35 | def trace_sin():
36 | """Plot a sine wave on the oscilloscope.
37 | """
38 | channels = Channel(), Channel()
39 | par = Par(GenerateFloats(channels[0]),
40 | Sin(channels[0], channels[1]),
41 | Oscilloscope(channels[1]))
42 | par.start()
43 | return
44 |
45 |
46 | def trace_cos():
47 | """Plot a cosine wave on the oscilloscope.
48 | """
49 | channels = Channel(), Channel()
50 | par = Par(GenerateFloats(channels[0]),
51 | Cos(channels[0], channels[1]),
52 | Oscilloscope(channels[1]))
53 | par.start()
54 | return
55 |
56 |
57 | def trace_mux():
58 | """Plot sine and cosine waves on the oscilloscope.
59 | """
60 | channels = [Channel() for i in range(6)]
61 | par = Par(GenerateFloats(channels[0]),
62 | Delta2(channels[0], channels[1], channels[2]),
63 | Cos(channels[1], channels[3]),
64 | Sin(channels[2], channels[4]),
65 | Mux2(channels[3], channels[4], channels[5]),
66 | Oscilloscope(channels[5]))
67 | par.start()
68 | return
69 |
70 | EXAMPLES = {}
71 | for name, func in globals().items():
72 | if name.startswith('trace_'):
73 | EXAMPLES[name[6:]] = func
74 |
75 | if __name__ == '__main__':
76 | if len(sys.argv) != 2:
77 | print('Syntax: python {0} {1}'.format(sys.argv[0],
78 | ' | '.join(EXAMPLES.keys())))
79 | for name, func in EXAMPLES.items():
80 | print(' {0:<9} {1}'.format(name, func.func_doc.strip()))
81 | elif sys.argv[1] not in EXAMPLES:
82 | print('Unknown example {0}'.format(sys.argv[1]))
83 | else:
84 | print('Use cursor up/down for scaling, s for save and q for quit')
85 | EXAMPLES[sys.argv[1]]()
86 |
87 |
--------------------------------------------------------------------------------
/tutorial/part08/Queue.dia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/tutorial/part08/Queue.dia
--------------------------------------------------------------------------------
/tutorial/part08/Queue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/futurecore/python-csp/1f96b76de1531ecf6bf1759641eadb08266ff7e7/tutorial/part08/Queue.png
--------------------------------------------------------------------------------