bocpy 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bocpy-0.1.0/LICENSE.md +21 -0
- bocpy-0.1.0/PKG-INFO +251 -0
- bocpy-0.1.0/README.md +214 -0
- bocpy-0.1.0/pyproject.toml +32 -0
- bocpy-0.1.0/setup.cfg +4 -0
- bocpy-0.1.0/setup.py +15 -0
- bocpy-0.1.0/src/bocpy/__init__.py +8 -0
- bocpy-0.1.0/src/bocpy/__init__.pyi +431 -0
- bocpy-0.1.0/src/bocpy/_core.c +3349 -0
- bocpy-0.1.0/src/bocpy/_math.c +2610 -0
- bocpy-0.1.0/src/bocpy/behaviors.py +521 -0
- bocpy-0.1.0/src/bocpy/py.typed +0 -0
- bocpy-0.1.0/src/bocpy/transpiler.py +291 -0
- bocpy-0.1.0/src/bocpy/worker.py +106 -0
- bocpy-0.1.0/src/bocpy.egg-info/PKG-INFO +251 -0
- bocpy-0.1.0/src/bocpy.egg-info/SOURCES.txt +20 -0
- bocpy-0.1.0/src/bocpy.egg-info/dependency_links.txt +1 -0
- bocpy-0.1.0/src/bocpy.egg-info/requires.txt +23 -0
- bocpy-0.1.0/src/bocpy.egg-info/top_level.txt +1 -0
- bocpy-0.1.0/test/test_boc.py +396 -0
- bocpy-0.1.0/test/test_matrix.py +2636 -0
- bocpy-0.1.0/test/test_message_queue.py +675 -0
bocpy-0.1.0/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Copyright (c) Microsoft Corporation.
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
bocpy-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bocpy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: boc is a Python extension that adds Behavior-oriented concurrency built on top of cross-interpreter data.
|
|
5
|
+
Author-email: Pyrona Team <pyrona@microsoft.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: homepage, https://microsoft.github.io/bocpy/
|
|
8
|
+
Project-URL: source, https://github.com/microsoft/bocpy
|
|
9
|
+
Project-URL: documentation, https://microsoft.github.io/bocpy/docs
|
|
10
|
+
Project-URL: issues, https://github.com/microsoft/bocpy/issues
|
|
11
|
+
Keywords: behavior-oriented,concurrency,subinterpreters
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE.md
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: pytest-md; extra == "test"
|
|
19
|
+
Requires-Dist: pytest-emoji; extra == "test"
|
|
20
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
21
|
+
Requires-Dist: pytest; extra == "test"
|
|
22
|
+
Provides-Extra: linting
|
|
23
|
+
Requires-Dist: flake8; extra == "linting"
|
|
24
|
+
Requires-Dist: flake8-bugbear; extra == "linting"
|
|
25
|
+
Requires-Dist: flake8-builtins; extra == "linting"
|
|
26
|
+
Requires-Dist: flake8-docstrings; extra == "linting"
|
|
27
|
+
Requires-Dist: flake8-import-order; extra == "linting"
|
|
28
|
+
Requires-Dist: flake8-quotes; extra == "linting"
|
|
29
|
+
Requires-Dist: pep8-naming; extra == "linting"
|
|
30
|
+
Provides-Extra: docs
|
|
31
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
32
|
+
Requires-Dist: sphinx-autodoc-typehints; extra == "docs"
|
|
33
|
+
Requires-Dist: enum-tools[sphinx]; extra == "docs"
|
|
34
|
+
Provides-Extra: boids
|
|
35
|
+
Requires-Dist: pyglet; extra == "boids"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# bocpy
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
Behavior-Oriented Concurrency (*BOC*) is a new paradigm for parallel and concurrent
|
|
43
|
+
programming which is particularly well-suited to Python. In a BOC program, data is
|
|
44
|
+
shared such that each behavior has unique temporal ownership of the data, removing
|
|
45
|
+
the need for locks to coordinate access. For Python programmers, this brings a lot
|
|
46
|
+
of benefits. Behaviors are implemented as decorated functions, and from the programmer's
|
|
47
|
+
perspective, those functions work like normal. Importantly, the programmer's task
|
|
48
|
+
shifts from solving concurrent data access problems to organizing data flow through
|
|
49
|
+
functions. The resulting programs are easier to understand, easier to support, easier
|
|
50
|
+
to extend, and unlock multi-core performance due to the ability to schedule behaviors
|
|
51
|
+
to run efficiently across multiple processes.
|
|
52
|
+
|
|
53
|
+
BOC has been implemented in several languages, including as a foundational aspect
|
|
54
|
+
of the research language Verona, and now has been implemented in Python.
|
|
55
|
+
|
|
56
|
+
## Getting Started
|
|
57
|
+
|
|
58
|
+
You can install `boc` via PyPi:
|
|
59
|
+
|
|
60
|
+
pip install bocpy
|
|
61
|
+
|
|
62
|
+
We provide pre-compiled wheels for Python 3.10 onwards on most platforms, but if
|
|
63
|
+
you have problems with your particular platform/version combination, please file
|
|
64
|
+
an issue on [this repository](https://github.com/microsoft/bocpy/issues).
|
|
65
|
+
|
|
66
|
+
> [!NOTE]
|
|
67
|
+
> the `boc` library depends on the Cross-Interpreter Data mechanism, which was
|
|
68
|
+
> introduced in Python 3.7. We explicitly test and provide wheels for all versions
|
|
69
|
+
> of Python that have not been end-of-lifed (3.10.19 as of time of writing is the
|
|
70
|
+
> oldest version we support). The library may not work in older versions of Python.
|
|
71
|
+
|
|
72
|
+
A behavior can be thought of as a function which depends on zero or more
|
|
73
|
+
concurrently-owned data objects (which we call **cowns**). As a programmer, you
|
|
74
|
+
indicate that you want the function to be called once all of those resources are
|
|
75
|
+
available. For example, let's say that you had two complex and time-consuming
|
|
76
|
+
operations, and you needed to act on the basis of both of their outcomes:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
|
|
80
|
+
def buy_cheese():
|
|
81
|
+
logger = logging.getLogger("cheese_shop")
|
|
82
|
+
for name in all_known_cheeses():
|
|
83
|
+
if is_available(logger, name):
|
|
84
|
+
return name
|
|
85
|
+
|
|
86
|
+
cleanup_shop(logger)
|
|
87
|
+
return None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def order_meal(exclude: str):
|
|
91
|
+
logger = logging.getLogger("greasy_spoon")
|
|
92
|
+
for dish in menu():
|
|
93
|
+
logger.info(dish)
|
|
94
|
+
if exclude.lower() not in dish.lower():
|
|
95
|
+
logger.info(f"That doesn't have much {exclude} in it")
|
|
96
|
+
return dish
|
|
97
|
+
|
|
98
|
+
vikings(logger)
|
|
99
|
+
if random.random() < 0.3:
|
|
100
|
+
logger.info("<bloody vikings>")
|
|
101
|
+
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
cheese = buy_cheese()
|
|
106
|
+
meal = order_meal(exclude="spam")
|
|
107
|
+
|
|
108
|
+
if meal is not None:
|
|
109
|
+
eat(meal)
|
|
110
|
+
elif cheese is not None:
|
|
111
|
+
eat(cheese)
|
|
112
|
+
|
|
113
|
+
if meal is not None:
|
|
114
|
+
print("I really wanted some cheese...")
|
|
115
|
+
elif cheese is not None:
|
|
116
|
+
print("Cheesy comestibles")
|
|
117
|
+
|
|
118
|
+
return_to_library()
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The code above will work, but requires the purveying of cheese and the navigation
|
|
122
|
+
of the menu for non-spam options to happen sequentially. If we wanted to do these
|
|
123
|
+
tasks in parallel, we will end up with some version of nested waiting, which can
|
|
124
|
+
result in deadlock. With BOC, we would write the above like this:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from bocpy import wait, when, Cown
|
|
128
|
+
|
|
129
|
+
# ...
|
|
130
|
+
|
|
131
|
+
def buy_cheese():
|
|
132
|
+
cheese = Cown(None)
|
|
133
|
+
|
|
134
|
+
@when(cheese)
|
|
135
|
+
def _(cheese):
|
|
136
|
+
logger = logging.getLogger("cheese_shop")
|
|
137
|
+
for name in all_known_cheeses():
|
|
138
|
+
if is_available(logger, name):
|
|
139
|
+
cheese.value = name
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
cleanup_shop(logger)
|
|
143
|
+
|
|
144
|
+
return cheese
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def order_meal(exclude: str):
|
|
148
|
+
order = Cown(None)
|
|
149
|
+
|
|
150
|
+
@when(order)
|
|
151
|
+
def _(order):
|
|
152
|
+
logger = logging.getLogger("greasy_spoon")
|
|
153
|
+
logger.info("We have...")
|
|
154
|
+
for dish in menu():
|
|
155
|
+
logger.info(dish)
|
|
156
|
+
if exclude.lower() not in dish.lower():
|
|
157
|
+
logger.info(f"That doesn't have much {exclude} in it")
|
|
158
|
+
order.value = dish
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
vikings(logger)
|
|
162
|
+
if random.random() < 0.3:
|
|
163
|
+
logger.info("<bloody vikings>")
|
|
164
|
+
|
|
165
|
+
return order
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
cheese = buy_cheese()
|
|
169
|
+
meal = order_meal(exclude="spam")
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
@when(cheese, meal)
|
|
173
|
+
def _(cheese, meal):
|
|
174
|
+
if meal.value is not None:
|
|
175
|
+
eat(meal.value)
|
|
176
|
+
elif cheese.value is not None:
|
|
177
|
+
eat(cheese.value)
|
|
178
|
+
else:
|
|
179
|
+
print("<stomach rumbles>")
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@when(cheese, meal)
|
|
183
|
+
def _(cheese, meal):
|
|
184
|
+
if meal.value is not None:
|
|
185
|
+
print("I really wanted cheese...")
|
|
186
|
+
elif cheese.value is not None:
|
|
187
|
+
print("Cheesy comestibles!")
|
|
188
|
+
|
|
189
|
+
return_to_library()
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
wait()
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
You can view the full example
|
|
196
|
+
[here](https://github.com/microsoft/bocpy/blob/main/examples/sketches.py)
|
|
197
|
+
|
|
198
|
+
The underlying BOC scheduler ensures that this operates without deadlock, by
|
|
199
|
+
construction.
|
|
200
|
+
|
|
201
|
+
### Examples
|
|
202
|
+
|
|
203
|
+
We provide a few examples to show different ways of using BOC in a program:
|
|
204
|
+
|
|
205
|
+
1. [Atomic Bank Transfer](https://github.com/microsoft/bocpy/blob/main/examples/bank.py): Shows an example
|
|
206
|
+
where two objects (in this case, bank accounts), interact in an atomic way.
|
|
207
|
+
2. [Dining Philosophers](https://github.com/microsoft/bocpy/blob/main/examples/dining_philosophers.py):
|
|
208
|
+
The classic Dining Philosphers problem implemented using BOC.
|
|
209
|
+
3. [Fibonacci](https://github.com/microsoft/bocpy/blob/main/examples/fibonacci.py): A
|
|
210
|
+
parallel implementation of Fibonacci calculation.
|
|
211
|
+
4. [Cooking](https://github.com/microsoft/bocpy/blob/main/examples/cooking_boc.py): The example from
|
|
212
|
+
the [BOC tutorial](https://microsoft.github.io/bocpy/).
|
|
213
|
+
5. [Boids](https://github.com/microsoft/bocpy/blob/main/examples/boids.py): An agent-based bird flocking
|
|
214
|
+
example demonstrating the `Matrix` class to do distributed computation over cores.
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
## Why BOC for Python?
|
|
218
|
+
For many Python programmers, the GIL has established a programming model in which
|
|
219
|
+
they do not have to think about the many potential issues that are introduced by
|
|
220
|
+
concurrency, in particular data races. One of the best features of BOC is that, due
|
|
221
|
+
to the way behaviors interact with concurrently owned data (*cowns*), each behavior
|
|
222
|
+
can operate over its data without a need to change this familiar programming model.
|
|
223
|
+
Even in a free-threading context, BOC will reduce contention on locks and provide
|
|
224
|
+
programs which are data-race free by construction. Our initial research and experiments
|
|
225
|
+
with BOC have shown near linear scaling over cores, with up to 32 concurrent worker
|
|
226
|
+
processes.
|
|
227
|
+
|
|
228
|
+
### This library
|
|
229
|
+
Our implementation is built on top of the subinterpreters mechanism and the
|
|
230
|
+
Cross-Interpreter Data, or `XIData`, API. As of Python 3.12, sub-interpreters have
|
|
231
|
+
their own GIL and thus run in parallel, and thus BOC will also run fully in
|
|
232
|
+
parallel.
|
|
233
|
+
|
|
234
|
+
In addition the providing the `when` function decorator, the library also exposes
|
|
235
|
+
low-level Erlang-style `send` and selective `receive` functions which enable
|
|
236
|
+
lock-free communication across threads and subinterpreters. See the
|
|
237
|
+
[Primes](https://github.com/microsoft/bocpy/blob/main/examples/primes.py) and
|
|
238
|
+
[Calculator](https://github.com/microsoft/bocpy/blob/main/examples/calculator.py)
|
|
239
|
+
examples for the usage of these lower-level functions.
|
|
240
|
+
|
|
241
|
+
### Additional Info
|
|
242
|
+
BOC is built on a solid foundation of serious scholarship and engineering. For further reading, please see:
|
|
243
|
+
1. [When Concurrency Matters: Behaviour-Oriented Concurrency](https://dl.acm.org/doi/10.1145/3622852)
|
|
244
|
+
2. [Reference implementation in C#](https://github.com/microsoft/verona-rt/tree/main/docs/internal/concurrency/modelimpl)
|
|
245
|
+
3. [OOPSLA23 Talk](https://www.youtube.com/watch?v=iX8TJWonbGU)
|
|
246
|
+
|
|
247
|
+
> **Trademarks** This project may contain trademarks or logos for projects, products, or services.
|
|
248
|
+
> Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft’s
|
|
249
|
+
> Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this
|
|
250
|
+
> project must not cause confusion or imply Microsoft sponsorship. Any use of third-party
|
|
251
|
+
> trademarks or logos are subject to those third-party’s policies.
|
bocpy-0.1.0/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# bocpy
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Behavior-Oriented Concurrency (*BOC*) is a new paradigm for parallel and concurrent
|
|
6
|
+
programming which is particularly well-suited to Python. In a BOC program, data is
|
|
7
|
+
shared such that each behavior has unique temporal ownership of the data, removing
|
|
8
|
+
the need for locks to coordinate access. For Python programmers, this brings a lot
|
|
9
|
+
of benefits. Behaviors are implemented as decorated functions, and from the programmer's
|
|
10
|
+
perspective, those functions work like normal. Importantly, the programmer's task
|
|
11
|
+
shifts from solving concurrent data access problems to organizing data flow through
|
|
12
|
+
functions. The resulting programs are easier to understand, easier to support, easier
|
|
13
|
+
to extend, and unlock multi-core performance due to the ability to schedule behaviors
|
|
14
|
+
to run efficiently across multiple processes.
|
|
15
|
+
|
|
16
|
+
BOC has been implemented in several languages, including as a foundational aspect
|
|
17
|
+
of the research language Verona, and now has been implemented in Python.
|
|
18
|
+
|
|
19
|
+
## Getting Started
|
|
20
|
+
|
|
21
|
+
You can install `boc` via PyPi:
|
|
22
|
+
|
|
23
|
+
pip install bocpy
|
|
24
|
+
|
|
25
|
+
We provide pre-compiled wheels for Python 3.10 onwards on most platforms, but if
|
|
26
|
+
you have problems with your particular platform/version combination, please file
|
|
27
|
+
an issue on [this repository](https://github.com/microsoft/bocpy/issues).
|
|
28
|
+
|
|
29
|
+
> [!NOTE]
|
|
30
|
+
> the `boc` library depends on the Cross-Interpreter Data mechanism, which was
|
|
31
|
+
> introduced in Python 3.7. We explicitly test and provide wheels for all versions
|
|
32
|
+
> of Python that have not been end-of-lifed (3.10.19 as of time of writing is the
|
|
33
|
+
> oldest version we support). The library may not work in older versions of Python.
|
|
34
|
+
|
|
35
|
+
A behavior can be thought of as a function which depends on zero or more
|
|
36
|
+
concurrently-owned data objects (which we call **cowns**). As a programmer, you
|
|
37
|
+
indicate that you want the function to be called once all of those resources are
|
|
38
|
+
available. For example, let's say that you had two complex and time-consuming
|
|
39
|
+
operations, and you needed to act on the basis of both of their outcomes:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
|
|
43
|
+
def buy_cheese():
|
|
44
|
+
logger = logging.getLogger("cheese_shop")
|
|
45
|
+
for name in all_known_cheeses():
|
|
46
|
+
if is_available(logger, name):
|
|
47
|
+
return name
|
|
48
|
+
|
|
49
|
+
cleanup_shop(logger)
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def order_meal(exclude: str):
|
|
54
|
+
logger = logging.getLogger("greasy_spoon")
|
|
55
|
+
for dish in menu():
|
|
56
|
+
logger.info(dish)
|
|
57
|
+
if exclude.lower() not in dish.lower():
|
|
58
|
+
logger.info(f"That doesn't have much {exclude} in it")
|
|
59
|
+
return dish
|
|
60
|
+
|
|
61
|
+
vikings(logger)
|
|
62
|
+
if random.random() < 0.3:
|
|
63
|
+
logger.info("<bloody vikings>")
|
|
64
|
+
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
cheese = buy_cheese()
|
|
69
|
+
meal = order_meal(exclude="spam")
|
|
70
|
+
|
|
71
|
+
if meal is not None:
|
|
72
|
+
eat(meal)
|
|
73
|
+
elif cheese is not None:
|
|
74
|
+
eat(cheese)
|
|
75
|
+
|
|
76
|
+
if meal is not None:
|
|
77
|
+
print("I really wanted some cheese...")
|
|
78
|
+
elif cheese is not None:
|
|
79
|
+
print("Cheesy comestibles")
|
|
80
|
+
|
|
81
|
+
return_to_library()
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The code above will work, but requires the purveying of cheese and the navigation
|
|
85
|
+
of the menu for non-spam options to happen sequentially. If we wanted to do these
|
|
86
|
+
tasks in parallel, we will end up with some version of nested waiting, which can
|
|
87
|
+
result in deadlock. With BOC, we would write the above like this:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from bocpy import wait, when, Cown
|
|
91
|
+
|
|
92
|
+
# ...
|
|
93
|
+
|
|
94
|
+
def buy_cheese():
|
|
95
|
+
cheese = Cown(None)
|
|
96
|
+
|
|
97
|
+
@when(cheese)
|
|
98
|
+
def _(cheese):
|
|
99
|
+
logger = logging.getLogger("cheese_shop")
|
|
100
|
+
for name in all_known_cheeses():
|
|
101
|
+
if is_available(logger, name):
|
|
102
|
+
cheese.value = name
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
cleanup_shop(logger)
|
|
106
|
+
|
|
107
|
+
return cheese
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def order_meal(exclude: str):
|
|
111
|
+
order = Cown(None)
|
|
112
|
+
|
|
113
|
+
@when(order)
|
|
114
|
+
def _(order):
|
|
115
|
+
logger = logging.getLogger("greasy_spoon")
|
|
116
|
+
logger.info("We have...")
|
|
117
|
+
for dish in menu():
|
|
118
|
+
logger.info(dish)
|
|
119
|
+
if exclude.lower() not in dish.lower():
|
|
120
|
+
logger.info(f"That doesn't have much {exclude} in it")
|
|
121
|
+
order.value = dish
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
vikings(logger)
|
|
125
|
+
if random.random() < 0.3:
|
|
126
|
+
logger.info("<bloody vikings>")
|
|
127
|
+
|
|
128
|
+
return order
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
cheese = buy_cheese()
|
|
132
|
+
meal = order_meal(exclude="spam")
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@when(cheese, meal)
|
|
136
|
+
def _(cheese, meal):
|
|
137
|
+
if meal.value is not None:
|
|
138
|
+
eat(meal.value)
|
|
139
|
+
elif cheese.value is not None:
|
|
140
|
+
eat(cheese.value)
|
|
141
|
+
else:
|
|
142
|
+
print("<stomach rumbles>")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@when(cheese, meal)
|
|
146
|
+
def _(cheese, meal):
|
|
147
|
+
if meal.value is not None:
|
|
148
|
+
print("I really wanted cheese...")
|
|
149
|
+
elif cheese.value is not None:
|
|
150
|
+
print("Cheesy comestibles!")
|
|
151
|
+
|
|
152
|
+
return_to_library()
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
wait()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
You can view the full example
|
|
159
|
+
[here](https://github.com/microsoft/bocpy/blob/main/examples/sketches.py)
|
|
160
|
+
|
|
161
|
+
The underlying BOC scheduler ensures that this operates without deadlock, by
|
|
162
|
+
construction.
|
|
163
|
+
|
|
164
|
+
### Examples
|
|
165
|
+
|
|
166
|
+
We provide a few examples to show different ways of using BOC in a program:
|
|
167
|
+
|
|
168
|
+
1. [Atomic Bank Transfer](https://github.com/microsoft/bocpy/blob/main/examples/bank.py): Shows an example
|
|
169
|
+
where two objects (in this case, bank accounts), interact in an atomic way.
|
|
170
|
+
2. [Dining Philosophers](https://github.com/microsoft/bocpy/blob/main/examples/dining_philosophers.py):
|
|
171
|
+
The classic Dining Philosphers problem implemented using BOC.
|
|
172
|
+
3. [Fibonacci](https://github.com/microsoft/bocpy/blob/main/examples/fibonacci.py): A
|
|
173
|
+
parallel implementation of Fibonacci calculation.
|
|
174
|
+
4. [Cooking](https://github.com/microsoft/bocpy/blob/main/examples/cooking_boc.py): The example from
|
|
175
|
+
the [BOC tutorial](https://microsoft.github.io/bocpy/).
|
|
176
|
+
5. [Boids](https://github.com/microsoft/bocpy/blob/main/examples/boids.py): An agent-based bird flocking
|
|
177
|
+
example demonstrating the `Matrix` class to do distributed computation over cores.
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
## Why BOC for Python?
|
|
181
|
+
For many Python programmers, the GIL has established a programming model in which
|
|
182
|
+
they do not have to think about the many potential issues that are introduced by
|
|
183
|
+
concurrency, in particular data races. One of the best features of BOC is that, due
|
|
184
|
+
to the way behaviors interact with concurrently owned data (*cowns*), each behavior
|
|
185
|
+
can operate over its data without a need to change this familiar programming model.
|
|
186
|
+
Even in a free-threading context, BOC will reduce contention on locks and provide
|
|
187
|
+
programs which are data-race free by construction. Our initial research and experiments
|
|
188
|
+
with BOC have shown near linear scaling over cores, with up to 32 concurrent worker
|
|
189
|
+
processes.
|
|
190
|
+
|
|
191
|
+
### This library
|
|
192
|
+
Our implementation is built on top of the subinterpreters mechanism and the
|
|
193
|
+
Cross-Interpreter Data, or `XIData`, API. As of Python 3.12, sub-interpreters have
|
|
194
|
+
their own GIL and thus run in parallel, and thus BOC will also run fully in
|
|
195
|
+
parallel.
|
|
196
|
+
|
|
197
|
+
In addition the providing the `when` function decorator, the library also exposes
|
|
198
|
+
low-level Erlang-style `send` and selective `receive` functions which enable
|
|
199
|
+
lock-free communication across threads and subinterpreters. See the
|
|
200
|
+
[Primes](https://github.com/microsoft/bocpy/blob/main/examples/primes.py) and
|
|
201
|
+
[Calculator](https://github.com/microsoft/bocpy/blob/main/examples/calculator.py)
|
|
202
|
+
examples for the usage of these lower-level functions.
|
|
203
|
+
|
|
204
|
+
### Additional Info
|
|
205
|
+
BOC is built on a solid foundation of serious scholarship and engineering. For further reading, please see:
|
|
206
|
+
1. [When Concurrency Matters: Behaviour-Oriented Concurrency](https://dl.acm.org/doi/10.1145/3622852)
|
|
207
|
+
2. [Reference implementation in C#](https://github.com/microsoft/verona-rt/tree/main/docs/internal/concurrency/modelimpl)
|
|
208
|
+
3. [OOPSLA23 Talk](https://www.youtube.com/watch?v=iX8TJWonbGU)
|
|
209
|
+
|
|
210
|
+
> **Trademarks** This project may contain trademarks or logos for projects, products, or services.
|
|
211
|
+
> Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft’s
|
|
212
|
+
> Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this
|
|
213
|
+
> project must not cause confusion or imply Microsoft sponsorship. Any use of third-party
|
|
214
|
+
> trademarks or logos are subject to those third-party’s policies.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "bocpy"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "Pyrona Team", email="pyrona@microsoft.com"}
|
|
10
|
+
]
|
|
11
|
+
description = "boc is a Python extension that adds Behavior-oriented concurrency built on top of cross-interpreter data."
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
keywords = ["behavior-oriented", "concurrency", "subinterpreters"]
|
|
14
|
+
license = "MIT"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
19
|
+
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.urls]
|
|
23
|
+
homepage = "https://microsoft.github.io/bocpy/"
|
|
24
|
+
source = "https://github.com/microsoft/bocpy"
|
|
25
|
+
documentation = "https://microsoft.github.io/bocpy/docs"
|
|
26
|
+
issues = "https://github.com/microsoft/bocpy/issues"
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
test = ["pytest-md", "pytest-emoji", "pytest-cov", "pytest"]
|
|
30
|
+
linting = ["flake8", "flake8-bugbear", "flake8-builtins", "flake8-docstrings", "flake8-import-order", "flake8-quotes", "pep8-naming"]
|
|
31
|
+
docs = ["sphinx", "sphinx-autodoc-typehints", "enum-tools[sphinx]"]
|
|
32
|
+
boids = ["pyglet"]
|
bocpy-0.1.0/setup.cfg
ADDED
bocpy-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Behavior-oriented Concurrency."""
|
|
2
|
+
|
|
3
|
+
from ._core import receive, send, set_tags, TIMEOUT
|
|
4
|
+
from ._math import Matrix
|
|
5
|
+
from .behaviors import Behaviors, Cown, start, wait, when, whencall, WORKER_COUNT
|
|
6
|
+
|
|
7
|
+
__all__ = ["Matrix", "send", "receive", "set_tags", "TIMEOUT", "start",
|
|
8
|
+
"wait", "when", "whencall", "Behaviors", "Cown", "WORKER_COUNT"]
|