Skip to content

Commit 4781742

Browse files
committed
Added documentation for event set compositions (closes #85)
1 parent beac93b commit 4781742

File tree

2 files changed

+70
-22
lines changed

2 files changed

+70
-22
lines changed

docs/source/BPjsTutorial/bp-object.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ Splits the calling b-thread to two identical b-threads. On the "parent" b-thread
6262

6363
Provides access to the logger. See :doc:`logging`.
6464

65+
``bp.eventSets``
66+
~~~~~~~~~~~~~~~~
67+
68+
Provides access to useful event sets methods and constant:
69+
70+
* ``bp.eventSets.all``: All events (an event set that contains all events).
71+
* ``bp.eventSets.none``: An event set that does not contain any event.
72+
* ``bp.eventSets.anyOf(e1, e2, e3)``: An event set that contains ``e1``, ``e2``, and ``e3``. Similar to ``e1.or(e2).or(e3)``.
73+
* ``bp.eventSets.allOf(s1, s2, s3)``: An event set that is the conjunction of ``s1``, ``s2``, and ``s3`` (so, contains only events that are in ``s1`` and ``s2`` AND ``s3``). Similar to ``e1.and(e2).and(e3)``.
74+
* ``bp.eventSets.not(es42)``: An event set containing all events that are not in ``es42``.
75+
76+
.. note::
77+
Recall that events are event sets themselves (technically, an event is an event set that contains a single event - itself). So whenever a method expects an event _set_, you can pass a regular event to it.
78+
79+
80+
81+
6582
``bp.random``
6683
~~~~~~~~~~~~~
6784

docs/source/BPjsTutorial/eventsets.rst

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,61 @@
22
Event Sets
33
==========
44

5-
When a b-thread requests an event, it has to be specific. That is, the b-thread has to provide an event instance as a parameter to ``bp.sync``. This is not the case for waited-for and blocked events: there are specified by an **event set**. An event set can be specified in the following ways:
5+
When a b-thread requests an event, it has to be specific. That is, the b-thread has to provide an event instance as a parameter to ``bp.sync``. This is not the case for waited-for and blocked events: these are specified by an **event set**. An event set contains other events. It is a set in the mathematical sense - it does not have to store the events it contains in a data structure, just to answer *yes* or *no* when asked whether it contains them. Accordingly, an event set is defined by a function that accepts an event and returns ``true`` or ``false``.
6+
7+
An event is a special type of event set - an event set that contains only itself. So we get that:
8+
9+
.. code:: javascript
10+
11+
const eventA = bp.Event("A");
12+
const eventB = bp.Event("B");
13+
14+
eventA.contains(eventA); // true
15+
eventA.contains(eventB); // false
16+
17+
An event set can be specified in the following ways:
618

719
* If the set contains a single event, the event itself serves as an event set. We used this in the :ref:`hello_world` example.
820

9-
* If the set contains some events known in advance, they can be passed as a value like so:
21+
* By composing events through their composition methods ``or``, ``and``, ``negate``, ``xor``, ``nor``, and ``nand``:
22+
23+
.. code:: javascript
24+
25+
const aOrB = bp.Event("A").or( bp.Event("B") ); // contains events "A" and "B"
26+
const notA = bp.Event("A").negate(); // all events except "A"
27+
const notAOrB = bp.Event("A").or( bp.Event("B") ).negate(); // contains all events
28+
// except for "A" and "B"
29+
30+
* By using the ``bp.eventSets`` utility object:
1031

1132
.. code:: javascript
1233
13-
bp.sync({waitFor:[evt1, evt2, evt3], block:[evt500]});
34+
const aOrB = bp.eventSets.anyOf( bp.Event("A"), bp.Event("B") );
35+
const conj = bp.eventSets.allOf( es1, es2 ); // events that are members of event sets ``es1`` and ``es2``.
36+
const notA = bp.eventSets.not( bp.Event("A") ); // all events except "A".
1437
15-
* By an ``EventSet`` object. These have name and a predicate that takes an event and returns a boolean result: ``true`` if the event is a member of the set, and ``false`` otherwise:
38+
* By an ``EventSet`` object. These have name and a predicate that takes an event and returns a boolean result: ``true`` if the event is a member of the set, and ``false`` otherwise. This way of defining event sets is verbose, but allows for fine-grained control over the set containment logic:
1639

1740
.. code:: Javascript
1841
19-
bp.EventSet( "name", function(evt){
20-
return /* computation about evt goes here */;
42+
bp.EventSet( "eventsWhoseNameStartsWithA", function(evt){
43+
return (evt.name.indexOf("A")==0);
2144
});
2245
23-
* By using one of the built-in event sets, ``bp.all``, which contains all events, or ``bp.none``, which is an empty set.
46+
47+
* An array of event sets is a translated to a disjunction (or) of those events (however, this is an old form which is not encouraged anymore, since it's not intuitive whether the semantics are of AND or of an OR).:
48+
49+
.. code:: javascript
50+
51+
bp.sync({waitFor:[evt1, evt2, evt3], block:evt500}); // same as evt1.or(evt2).or(evt3)
52+
53+
.. tip::
54+
The utility object ``bp.eventSets`` has two useful event set constants: ``bp.eventSets.all``, which contains all events, and ``bp.eventSets.none``, which is an empty set.
2455

2556
Example: Keep Serving Coffee
2657
----------------------------
2758

28-
Consider a coffee shop that serves some teas, sparkling water, and -- surprise -- coffees. Customers come and request their drink. To make sure the coffee is always freshly ground, the ground coffee container is just large enough to contain amount needed for ten cups. Thus, after the tenth coffee, the baristas has to stop taking coffee orders and go grind some coffee. They can serve other orders, though. The code below (:download:`full source <code/eventsets.js>`) models this.
59+
Consider a coffee shop that serves some teas, sparkling water, and -- surprise -- coffees. Customers come and request their drink. To make sure the coffee is always freshly ground, the ground coffee container is just large enough to contain the amount needed for ten cups. Thus, after the tenth coffee, the baristas has to stop taking coffee orders and go grind some coffee. They can serve other orders, though. The code below (:download:`full source <code/eventsets.js>`) models this.
2960

3061
First off, we need to generate the orders. Nothing fancy here, just your usual event requesting for-loop.
3162

@@ -46,7 +77,7 @@ After defining the event set for coffee orders, the "coffee supply" b-thread loo
4677

4778
.. note:: Rather than counting how many coffees were made using some variable, the "coffee supply" b-thread loops for 10 times, waiting for coffee to be ordered. This is an example for the classic scenario style: X has to happen Y times, and then we do Z.
4879

49-
Here's a sample output of this b-program:
80+
Here's a sample output of this b-program (annotated):
5081

5182
.. code:: bash
5283
@@ -58,30 +89,30 @@ Here's a sample output of this b-program:
5889
---:BPjs Started
5990
--:BPjs Event [BEvent name:green tea]
6091
--:BPjs Event [BEvent name:green tea]
61-
--:BPjs Event [BEvent name:espresso coffee]
62-
--:BPjs Event [BEvent name:latte coffee]
92+
--:BPjs Event [BEvent name:espresso coffee] «1»
93+
--:BPjs Event [BEvent name:latte coffee] «2»
6394
--:BPjs Event [BEvent name:sparkling water]
64-
--:BPjs Event [BEvent name:espresso coffee]
95+
--:BPjs Event [BEvent name:espresso coffee] «3»
6596
--:BPjs Event [BEvent name:black tea]
66-
--:BPjs Event [BEvent name:espresso coffee]
67-
--:BPjs Event [BEvent name:latte coffee]
97+
--:BPjs Event [BEvent name:espresso coffee] «4»
98+
--:BPjs Event [BEvent name:latte coffee] «5»
6899
--:BPjs Event [BEvent name:black tea]
69100
--:BPjs Event [BEvent name:black tea]
70101
--:BPjs Event [BEvent name:sparkling water]
71102
--:BPjs Event [BEvent name:sparkling water]
72-
--:BPjs Event [BEvent name:espresso coffee]
73-
--:BPjs Event [BEvent name:flatwhite coffee]
74-
--:BPjs Event [BEvent name:espresso coffee]
75-
--:BPjs Event [BEvent name:latte coffee]
103+
--:BPjs Event [BEvent name:espresso coffee] «6»
104+
--:BPjs Event [BEvent name:flatwhite coffee] «7»
105+
--:BPjs Event [BEvent name:espresso coffee] «8»
106+
--:BPjs Event [BEvent name:latte coffee] «9»
76107
--:BPjs Event [BEvent name:black tea]
77-
--:BPjs Event [BEvent name:espresso coffee]
78-
--:BPjs Event [BEvent name:Grind more coffee!]
79-
--:BPjs Event [BEvent name:flatwhite coffee]
108+
--:BPjs Event [BEvent name:espresso coffee] «10»
109+
--:BPjs Event [BEvent name:Grind more coffee!] «**Grind**»
110+
--:BPjs Event [BEvent name:flatwhite coffee] «11»
80111
--:BPjs Event [BEvent name:sparkling water]
81112
--:BPjs Event [BEvent name:black tea]
82113
... continues ...
83114
84115
Creating Complex Behaviors Using Simpler Ones
85116
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
86117

87-
The coffee shop program also serves as an example for the BP way of composing complex behavior from simpler ones. Baristas serves drinks when they are ordered. They also grind coffee when the ground coffee supply is low. Using BP, these behaviors can be described separately by the programmer, so they are easy to maintain and reason about. At runtime, the BP execution engine -- BPjs, in our case -- combines them to the required complex behavior.
118+
The coffee shop program also serves as an example for the BP way of composing complex behavior from simpler ones. Baristas serves drinks when they are ordered. They also grind coffee when the ground coffee supply is low. Using BP, these behaviors can be described separately by the programmer, so they are easy to maintain and reason about. At runtime, the BP execution engine -- BPjs, in our case -- combines them into the required complex behavior.

0 commit comments

Comments
 (0)