Skip to content

Commit

Permalink
Merged from develop: release
Browse files Browse the repository at this point in the history
  • Loading branch information
michbarsinai committed Jul 5, 2017
2 parents 7b092c0 + 1ee2660 commit 596dfc7
Show file tree
Hide file tree
Showing 84 changed files with 2,658 additions and 729 deletions.
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ This repository contains a javascript-based [BP](http://www.b-prog.org) library.
* BPjs is open sourced under the [MIT license](http://www.opensource.org/licenses/mit-license.php). If you use it in a system, please provide
a link to this page somewhere in the documentation/system about section.
* BPjs uses the Mozilla Rhino Javascript engine. See [here](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino) for project page and source code.

---

## Getting BPjs
* From Maven: Add as dependency to a Maven project. Note that the version number changes.
* For Maven projects: Add bpjs as dependency. Note that the version number changes.

````xml
<dependencies>
Expand All @@ -33,10 +33,44 @@ a link to this page somewhere in the documentation/system about section.
* Clone, fork, or download the [starting project](https://github.com/bThink-BGU/SampleBPjsProject).
* Download the `.jar` files directly from [Maven Central](https://repo.maven.apache.org/maven2/com/github/bthink-bgu/BPjs/).

## Documentation

* [Introductory Presentation](https://www.slideshare.net/MichaelBarSinai/introducing-bpjs-web)
* [Tutorial and Reference](http://bpjs.readthedocs.io/en/develop/)
* [API Javadocs](http://www.javadoc.io/doc/com.github.bthink-bgu/BPjs/)

## Change log for the BPjs library.

## 2017-07-05
* :sparkles: `bsync` now has an extra parameter, allowing b-threads to pass hinting data to custom `EventSelectionStrategy`s.
* :arrows_counterclockwise: Moved event selection strategy to `BProgram`.
* :sparkles: Added a mechanism to log the `BProgramState` at sync points.

## 2017-06-08
* :sparkles: Added documentation for embedding BPjs programs in larger Java apps.

## 2017-05-16
* :sparkles: README includes a more prominent reference to the documentation.

## 2017-05-10
* :sparkles: Added an adapter class for `BProgramListener`.
* :bug: Fixed issues with adding objects to the program's scope.

## 2017-04-08
* :put_litter_in_its_place: Cleaned up the `BProgramRunner`-`BProgram`-`BProgramSyncSnapshot` trio such that listeners don't have to be passed around between them.
* :sparkles: Cloning of `BProgramSyncSnapshot` ready. This is the basis for search.

### 2017-03-22

* :sparkles: New architecture: Running logic moved from `BProgram` to `BProgramRunner` - ongoing.
* :sparkles: `BProgramListener`s notified before BPrograms are started.
* :bug: Fixed a bug where dynamically added b-threads that were added by other dynamically added b-threads would run one cycle too late.
* :bug: Fixed a bug where external events enqueued from top-level JS code where ignored.

### 2017-03-21

* :sparkles: New architecture: Running logic moved from `BProgram` to `BProgramRunner`. This will help implementing search.
* :sparkles: `BProgramListener`s notified when a b-thread runs to completion.
* :sparkles: `bp.getTime()` added.
* :sparkles: Updated tutorial now includes the `bp` object.

Expand Down
4 changes: 2 additions & 2 deletions dependency-reduced-pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<groupId>com.github.bthink-bgu</groupId>
<artifactId>BPjs</artifactId>
<name>BPjs</name>
<version>0.8.4-SNAPSHOT</version>
<version>0.8.5-SNAPSHOT</version>
<description>Provides a runtime for behavioral programs written in Javascript. It can
run stand-alone (from the commmandline) or be embedded in larger
JVM-based systems.</description>
Expand Down Expand Up @@ -73,7 +73,7 @@
<profile>
<id>uber-jar</id>
<build>
<finalName>BPjs-${version}.uber</finalName>
<finalName>BPjs-${project.version}.uber</finalName>
<plugins>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
Expand Down
4 changes: 4 additions & 0 deletions docs/source/BPjsTutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ After calling ``bsync``, the b-thread is blocked, waiting for the rest of the b-

Behavioral Programming was introduced by Harel, Marron and Weiss in 2012 in a `paper`_ published at the *Communications of the ACM*.

.. note:: The ``bsync``\s in BPjs expand on the "classic" ``bsync``\s defined in the ACM paper: it contains an :doc:`interrupt <interrupts>` event set, and may contain a hint to the :doc:`event selection strategy <../extendBPjs/implement-ess>`.

.. _paper: http://cacm.acm.org/magazines/2012/7/151241-behavioral-programming/fulltext
.. _ACM Transactions on Computer Science: http://todo/fill/this

Expand All @@ -23,6 +25,8 @@ Tutorial
This tutorial will introduce you to BP principles and to the BPjs api. After completing it, you will be able to write BPjs programs. That's the technical part, though. Properly thinking in BP and in general scenario-based programming - well, that would probably take longer, as with any new programming paradigm.

.. toctree::
:maxdepth: 2

hello-world
eventsets
logging
Expand Down
2 changes: 1 addition & 1 deletion docs/source/_static/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ h3 {
}

.note {
background-color: rgba(128,255,128,.4);
background-color: #4ecb96;
}

.tip {
Expand Down
Binary file added docs/source/_static/css/custom.pdf
Binary file not shown.
100 changes: 94 additions & 6 deletions docs/source/embed-bpjs.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,102 @@
Embedding BPjs in an Application
================================

.. todo:: Write this.
Overview
--------

We'll have:
The BPjs library can be embedded in larger Java programs. The setting is useful in
cases where you want the control logic to be implemented using behavioral programming,
and thus need to translate incoming signals to BP events, and selected BP events to
instructions to, e.g. actuators, databases, or web-services.

* ref to inclusion in project
The layers of an application running a BPjs ``BProgram`` are described in the figure below.
The BP code (top layer) is the BPjs code, written in Javascript. It can interact with
the BPjs runtime using the :doc:`BPjsTutorial/bp-object`. The host application can make
other Java objects available to the Javascript code, as will be explained later.

* add listeners
The BPjs layer serves as a runtime environment for the BProgram. The host application has
to instantiate a ``BProgram`` object, and pass it to a ``BProgramRunner``. The host application
can listen to events of the running b-program (such as start, end, b-thread added, and - of course - b-event selected).
Additionally, the host application can provide custom event selection strategy, in case
the default one it not good enough.

* set daemon mode

* push an event
.. figure:: images/BPjs-stack.png
:scale: 50%
:alt: Running BPjs application stack
:align: center

The layers of a running BPjs program. The BP program, written in Javascript,
it the top layer. It interacts with the BPjs runtime using ``bp``,
a Javascript object added to its context. The hosting Java application controls
the BPjs runtime via its API. It can push event to the ``BProgram``'s external
event queue, and register listeners that are invoked when events are selected.


.. figure:: images/bprogram-running.png
:alt: Class diagram for running a BProgram
:align: center

Class diagram describing the strucutre of an embedded b-program. The client code
generates a BProgram and a BProgramRunner. The runner object consults the b-program's
event selection strategy when selecting events for the b-program it runs. A list of
listener objects are informed whenever an event of interest, such as b-thread
addition or b-event selection, occures.
*Some methods and properties have been omitted for brevity.*


.. note::
**Why is ``BProgram`` separated from ``BProgramRunner``?**

Because a b-program is also
a model that can be *verified* rather than *ran*. The same ``BProgram``
object can be passed to a verifier object for verification.



Steps for B-Program Embedding
-----------------------------

Code setup
~~~~~~~~~~

Add BPjs to your classpath.

See :doc:`install-bpjs`.

Decide which ``BProgram`` subclass you need.

`BProgram`_ is an abstract class. Its concrete sub-classes differ on how they obtain their source code. `SingleResourceBProgram`_ reads the code from a resource included with the code (typlically, a .js file bundled in the project's .jars). `StringBProgram`_, on the other hand, takes a Java String as source. Of course, ``BProgram`` can be directly extended as needed.

Write the BPjs code.

The code will interact with the runtime using the ``bp`` object. Additional Java classes can be made available to it by using Rhino's `import directives`_, or by adding Java objects to the program's scope (see below).

At Runtime
~~~~~~~~~~

* Instantiate the proper ``BProgram`` sub-class, and supply it with the source BPjs code.
* If needed, set a new ``EventSelectionStrategy``. When no strategy is supplied, SimpleEventSelectionStrategy_ will by used. This strategy randomly selects an event from the set of events that are requested and not blocked.
* If needed, add Java objects to the global b-program scope using `putInGlobalScope`_.
* Instantiate a ``BProgramRunner`` object, and supply it with the ``BProgram`` instance.
* Add listeners to the runner.
* In the common case when the program needs to wait for external events (such as GUI interactions), set the ``isDaemon`` property of the ``BProgram`` to ``true``.
* Call ``BProgramRunner::start()``.

The BProgram will start running. Lifecycle and behavioral events will be passed to the listener objects. In case the host application would like to push an external event to the embedded b-program (e.g. because of a network request, or a user click), it should use the ``BProgram``'s `enqueueExternalEvent`_ method.

.. tip::
BPjs' source code contains many examples of embedded BPjs programs - most of the unit tests that involve a b-program. For a more complete example, refer to the `RunFile`_ class, which implements the command-line tool for running BPjs code.

.. tip::
SampleBPjsProject_ can serve as a template project for embedding BPjs in a Java application. You can fork it on GitHub and start building your application from there.

.. _import directives: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java
.. _BProgram: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.4/il/ac/bgu/cs/bp/bpjs/bprogram/runtimeengine/BProgram.html
.. _SingleResourceBProgram: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.4/il/ac/bgu/cs/bp/bpjs/bprogram/runtimeengine/SingleResourceBProgram.html
.. _StringBProgram: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.4/il/ac/bgu/cs/bp/bpjs/bprogram/runtimeengine/StringBProgram.html
.. _putInGlobalScope: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.4/il/ac/bgu/cs/bp/bpjs/bprogram/runtimeengine/BProgram.html#putInGlobalScope-java.lang.String-java.lang.Object-
.. _enqueueExternalEvent: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.4/il/ac/bgu/cs/bp/bpjs/bprogram/runtimeengine/BProgram.html#enqueueExternalEvent-il.ac.bgu.cs.bp.bpjs.events.BEvent-
.. _RunFile: https://github.com/bThink-BGU/BPjs/blob/develop/src/main/java/il/ac/bgu/cs/bp/bpjs/mains/RunFile.java
.. _SimpleEventSelectionStrategy: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.4/il/ac/bgu/cs/bp/bpjs/eventselection/SimpleEventSelectionStrategy.html
.. _SampleBPjsProject: https://github.com/bThink-BGU/SampleBPjsProject
4 changes: 3 additions & 1 deletion docs/source/execute-bpjs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ The example below executes the code from f1.js and the clipboard. ``pbpaste`` is
pbpaste | java -jar <path-to-uber-jar> f1.js -


.. tip:: Unsure about why an event was or was not selected? Add a ``-v`` (for "verbose") switch to the above commandline. BPjs will print the synchronization statement for each BThread during program synchronization points.

From Java Code
---------------------

.. todo:: write this
BPjs programs can be embedded in larger Java (or any JVM langauge) applications. To learn how to run and interact with a BPjs program from a host application, see :doc:`embed-bpjs`.


.. _Java: https://www.java.com/en/
8 changes: 0 additions & 8 deletions docs/source/extend-bpjs.rst

This file was deleted.

12 changes: 12 additions & 0 deletions docs/source/extendBPjs/code/b-prog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
bp.registerBThread("bt-1", function () {
bsync({ request: bp.Event("1") }, 1);
});

bp.registerBThread("bt-2", function () {
bsync({ request: bp.Event("2") }, 2);
});

// Has no extra data on the bsync call.
bp.registerBThread("bt-3", function () {
bsync( {request: bp.Event("3")} );
});
55 changes: 55 additions & 0 deletions docs/source/extendBPjs/code/ess.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class PriorityEss implements EventSelectionStrategy {

@Override
public Set<BEvent> selectableEvents(Set<BSyncStatement> statements, List<BEvent> externalEvents) {

EventSet blocked = ComposableEventSet.anyOf(statements.stream()
.filter( stmt -> stmt!=null )
.map(BSyncStatement::getBlock )
.filter(r -> r != EventSets.none )
.collect( Collectors.toSet() ) );

Iterator<BSyncStatement> stmts = statements.iterator();
if ( stmts.hasNext() ) {
BSyncStatement firstStmt = stmts.next();
Set<BEvent> selectable = getNotBlocked(firstStmt, blocked);
int minValue = getValue( firstStmt );

while ( stmts.hasNext() ) {
BSyncStatement curStmt = stmts.next();
int curValue = getValue(curStmt);
if ( curValue < minValue ) {
minValue = curValue;
selectable = getNotBlocked(curStmt, blocked);
}
}
return new HashSet<>(selectable);
} else {
return Collections.emptySet();
}
}

@Override
public Optional<EventSelectionResult> select(Set<BSyncStatement> statements, List<BEvent> externalEvents, Set<BEvent> selectableEvents) {
if ( selectableEvents.isEmpty() ) {
return Optional.empty();
} else {
return Optional.of( new EventSelectionResult(selectableEvents.iterator().next()));
}
}

private int getValue( BSyncStatement stmt ) {
return stmt.hasData() ? ((Number)stmt.getData()).intValue() : Integer.MAX_VALUE;
}

private Set<BEvent> getNotBlocked(BSyncStatement stmt, EventSet blocked) {
try {
Context.enter();
return stmt.getRequest().stream()
.filter( req -> !blocked.contains(req) )
.collect( toSet() );
} finally {
Context.exit();
}
}
}
59 changes: 59 additions & 0 deletions docs/source/extendBPjs/implement-ess.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Alter Event Selection Algorithm
===============================

In standard behavioral programming, the b-thread coordinator, or b-program, is allowed to choose any event that is *requested and not blocked*. Even on modestly sized b-programs, this leaves the event selection algorithm with plenty of wiggle room to make its choice. By default, BPjs will randomly select a requested-and-not-blocked event. Algorithms that make more informed choices are, of course, possible. BPjs makes it easy to develop them, and make them reusable.


Meet ``EventSelectionStrategy``
-------------------------------

Each b-program has an event selection strategy, implementing the `EventSelectionStrategy`_ interface. Given a b-program state at a synchronization point, an ``EventSelectionStrategy`` object can generate a set of selectable events, and then select a single event out of them. Accordingly, the ``EventSelectionStrategy`` interface defines only two methods: ``selectableEvents(...)`` and ``select(...)``.

The event selection strategy is used during both program execution and verification. During verification, the strategy is used to generate the possible selectable events; during execution, the strategy both generates the selectable eventset and selects a single event.

Both of ``EventSelectionStrategy``\'s methods accept the program's state at the synchronization point. This state is composed of all the b-sync statements of participating b-threads, and the external event queue. ``selectableEvents`` returns a plain-old Java ``Set``, that can also possibly be empty. During execution, ``select`` recieves the program's state as well as the selectable event set obtained from the call to ``selectableEvents``. It does not return an ``Event``, though -- it returns a richer ``Optional<EventSelectionResult>`` object.

The `EventSelectionResult`_ object holds a selected event, and a set of indices to events in the external event queue. When receiving an `EventSelectionResult`, the b-program will remove the external events at those indices. This allows an event selection strategy a considerable degree of freedom for dealing with external event sets. For example, it can make the event list act like a set, by passing all the indices of events that are equal to the selected event.


Hinted ``bsync``\s
------------------

Some event selection strategies may depend on internal b-thread state. For example, a b-thread may define a HOT/COLD modality, as defined by Live Sequence Charts. A b-thread in a "HOT" state must advance, whereas a b-thread in a "COLD" state can forever stay in its current position without violating the system's specification.

To this end, the ``bsync`` statement in BPjs has an optional second parameter. BPjs makes no assumptions about the type of this parameter - it just stores it in the b-thread's `synchronization statement`_, where is it made available to the event selection strategy through the ``getData()`` method.


Sample Strategy: Priority-Based Selection
-----------------------------------------

Let's look at a sample event selection strategy, based on priority. Under this strategy, the b-threads may add to their ``bsync`` statements a "priority" integer. The strategy finds a b-thread with the lowest priority, and selects an event that it requested, and was not blocked. Here's the code, followed by a short discussion.

.. literalinclude:: code/ess.java
:linenos:
:language: java


The ``selectableEvents`` method begins by creating a set of all blocked events (lines 6-10). It then iterates over the ``BSyncStatement``\s, maintaining the minimal value it found so far. If a lower value is found, it creates a set of the events it requested and were not blocked (lines 15 and 23). Lastly, it returns the last such set found (line 26).

Since all of the work was done in the ``selectableEvents`` method, the ``select`` method has very little left to do: it selects the first event from the selectable event set passed to it. If that set is empty, it returns the empty ``Optional``.

There are two other interesting methods in this code. ``getValue`` (lines 41-43) extracts the priority integer from the statement. Note that the strategy also deals with a case where no such integer was provided.

``getNotBlocked`` (lines 45-54) takes a ``BSyncStatement`` and a blocked ``EventSet``, and returns the non-blocked subset of events requested by the statement. Note that ``EventSet`` is not ``Set<Event>`` -- ``EventSet`` is a predicate, an interface consisting of a single method: ``contains``. Quite often it will include one or more Javascript functions that have to be evaluated. For this reason, ``getNotBlocked`` has to enter and exit a Javascript execution context (lines 47 and 52, respectively).

The b-program using this event selection strategy is shown below. Note that b-threads "bt-1" and "bt-2" provide a priority integer, while "bt-3" does not.

.. literalinclude:: code/b-prog.js
:linenos:
:language: javascript

.. warning:: The above strategy is intended for explenatory purposes, and is probabaly too simplistic for real-world use. It ignores external events, assumes priorities are unique, and if all the events requested by the b-thread with the lowest priority are blocked, it claims there are no selectable events.

.. tip:: The above strategy and b-program are part of BPjs' `unit tests`_.


.. _EventSelectionStrategy: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.5/il/ac/bgu/cs/bp/bpjs/eventselection/EventSelectionStrategy.html
.. _EventSelectionResult: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.5/il/ac/bgu/cs/bp/bpjs/eventselection/EventSelectionResult.html
.. _synchronization statement: http://static.javadoc.io/com.github.bthink-bgu/BPjs/0.8.5/il/ac/bgu/cs/bp/bpjs/bprogram/runtimeengine/BSyncStatement.html
.. _unit tests: https://github.com/bThink-BGU/BPjs/blob/develop/src/test/java/il/ac/bgu/cs/bp/bpjs/examples/StatementsWithDataTest.java
Loading

0 comments on commit 596dfc7

Please sign in to comment.