Module gen_pnet

Callback function definitions and API for the gen_pnet behavior.

Copyright © 2016-2017 Jörgen Brandt

Version: 0.1.7

Behaviours: gen_server.

This module defines the gen_pnet behaviour.
Required callback functions: place_lst/0, trsn_lst/0, init_marking/2, preset/1, is_enabled/3, fire/3, code_change/3, handle_call/3, handle_cast/2, handle_info/2, init/1, terminate/2, trigger/3.

Authors: Jörgen Brandt (joergen.brandt@onlinehome.de).

Description

Callback function definitions and API for the gen_pnet behavior.

Net Structure Callback Functions

There are six callbacks that define the Petri net structure and its initial marking:

We have a look at each of them in turn.

place_lst/0

The place_lst/0 function lets us define the names of all places in the net.

Example:
  place_lst() ->
    [coin_slot, cash_box, signal, storage, compartment].

Here, we define the net to have the five places in the cookie vending machine.

trsn_lst/0

The trsn_lst/0 function lets us define the names of all transitions in the net.

Example:
  trsn_lst() ->
    [a, b].

Here, we define the net to have the two places a and b in the cookie vending machine.

preset/1

The preset/1 lets us define the preset places of a given transition.

Example:
  preset( a ) -> [coin_slot];
  preset( b ) -> [signal, storage].

Here, we define the preset of the transition a to be just the place coin_slot while the transition b has the places signal and storage in its preset.

init_marking/2

The init_marking/2 function lets us define the initial marking for a given place in the form of a token list. The argument UsrInfo is the user info field that has been generated in the actor interface callback init/1.

Example:
  init_marking( storage, _UsrInfo ) -> [cookie_box, cookie_box, cookie_box];
  init_marking( _Place, _UsrInfo )  -> [].

Here, we initialize the storage place with three cookie_box tokens. All other places are left empty.

is_enabled/3

The is_enabled/3 function is a predicate determining whether a given transition is enabled in a given mode. The UsrInfo argument is the user info field that has been created with init/1.

Example:
  is_enabled( a, #{ coin_slot := [coin] }, _UsrInfo )                      -> true;
  is_enabled( b, #{ signal := [sig], storage := [cookie_box] }, _UsrInfo ) -> true;
  is_enabled( _Trsn, _Mode, _UsrInfo )                                     -> false.

Here, we state that the transition a is enabled if it can consume a single coin from the coin_slot place. Similarly, the transition b is enabled if it can consume a sig token from the signal place and a cookie_box token from the storage` place. No other configuration can enable a transition. E.g., managing to get a `button token on the coin_slot place will not enable any transition.

fire/3

The fire/3 function defines what tokens are produced when a given transition fires in a given mode. As arguments it takes the name of the transition, and a firing mode in the form of a hash map mapping place names to token lists. The fire/3 function is called only on modes for which is_enabled/3 returns true. The fire/3 function is expected to return either a {produce, ProduceMap} tuple or the term abort. If abort is returned, the firing is aborted. Nothing is produced or consumed.

Example:
  fire( a, _Mode, _UsrInfo ) ->
    {produce, #{ cash_box => [coin], signal => [sig] }};
  fire( b, _Mode, _UsrInfo ) ->
    {produce, #{ compartment => [cookie_box] }}.

Here, the firing of the transition a produces a coin token on the cash_box place and a sig token on the signal place. Similarly, the firing of the transition b produces a cookie_box token on the compartment place. We do not need to state the tokens to be consumed because the firing mode already uniquely identifies the tokens to be consumed.

Interface Callback Functions

In addition to the structure callback functions there are another seven callback functions that determine how the net instance appears as an Erlang actor to the outside world:

code_change/3

The code_change/3 function determines what happens when a hot code reload appears. This callback is identical to the code_change/3 function in the gen_server behavior.

Example:
  code_change( _OldVsn, NetState, _Extra ) -> {ok, NetState}.

handle_call/3

The handle_call/3 function performs a synchronous exchange of messages between the caller and the net instance. The first argument is the request message, the second argument is a tuple identifying the caller, and the third argument is a #net_state{} record instance describing the current state of the net. The handle_call/3 function can generate a reply without changing the net marking by returning a {reply, Reply} tuple, it can generate a reply, consuming or producing tokens by returning a {reply, Reply, ConsumeMap, ProduceMap} tuple, it can defer replying without changing the net marking by returning noreply, it can defer replying, consuming or producing tokens by returning a {noreply, ConsumeMap, ProduceMap} tuple, or it can stop the net instance by returning {stop, Reason, Reply}.

Example:
  handle_call( insert_coin, _From, _NetState ) ->
    {reply, ok, #{}, #{ coin_slot => [coin] }};
 
  handle_call( remove_cookie_box, _From, NetState ) ->
 
    case gen_pnet:get_ls( compartment, NetState ) of
      []    -> {reply, {error, empty_compartment}};
      [_|_] -> {reply, ok, #{ compartment => [cookie_box] }, #{}}
    end;
 
  handle_call( _Request, _From, _NetState ) -> {reply, {error, bad_msg}}.

Here, we react to two kinds of messages: Inserting a coin in the coin slot and removing a cookie box from the compartment. Thus, we react to an insert_coin message by replying with ok, consuming nothing and producing a coin token on the coin_slot place. When receiving a remove_cookie_box message, we check whether the compartment place is empty, replying with an error message if it is, otherwise replying with ok, consuming one cookie_box token from the compartment place, and producing nothing. Calls that are neither insert_coin nor remove_cookie_box are responded to with an error message.

handle_cast/2

The handle_cast/2 function reacts to an asynchronous message received by the net instance. The first argument is the request while the second argument is a #net_state{} record instance. The handle_cast/2 function can either leave the net unchanged by returning noreply or it can consume or produce tokens by returning a {noreply, ConsumeMap, ProduceMap} tuple.

Example:
  handle_cast( _Request, _NetState ) -> noreply.

Here, we just ignore any cast.

handle_info/2

The handle_info/2 function reacts to an asynchronous, unformatted message received by the net instance. The first argument is the message term while the second argument is a #net_state{} record instance. The handle_info/2 function can either leave the net unchanged by returning noreply or it can consume or produce tokens by returning a {noreply, ConsumeMap, ProduceMap} tuple.

Example:
  handle_info( _Request, _NetState ) -> noreply.

Here, we just ignore any message.

init/1

The init/1 function initializes the net instance. It is given an initial argument which is provided with gen_pnet:start_link/n. The init/1 function is expected to return a user info field which is later handed to other callback functions.

Example:
  init( _NetArg ) -> [].

Here, we return the empty list as a dummy user info field.

terminate/2

The terminate/2 function determines what happens when the net instance is stopped. The first argument is the reason for termination while the second argument is a #net_state{} record instance. This callback is identical to the terminate/2 function in the gen_server behavior.

Example:
  terminate( _Reason, _NetState ) -> ok.

trigger/3

The trigger/3 function determines what happens when a token is produced on a given place. Its first argument Place is the place name, its second argument Token is the token about to be produced, and its third argument NetState is the current state of the net. The trigger/3 function is expected to return either pass in which case the token is produced normally, or drop in which case the token is forgotten.

Example:
  trigger( _Place, _Token, _NetState ) -> pass.
Here, we simply let any token pass.

Data Types

name()

name() = atom() | {atom(), atom()} | {global, term()} | {via, atom(), term()} | pid()

prop()

prop() = atom() | {atom(), term()}

server_name()

server_name() = {local, atom()} | {global, atom()} | {via, atom(), term()}

start_link_result()

start_link_result() = {ok, pid()} | ignore | {error, term()}

Function Index

call/2Synchronously send the term Request to the net instance identified as Name and return the reply.
call/3Synchronously send the term Request to the net instance identified as Name and return the reply.
cast/2Asynchronously send the term Request to the net instance identified as Name.
get_ls/2Extracts the list of tokens on a given place from a given net state.
get_stats/1Extracts the stats field from a given net instance.
get_usr_info/1Extracts the user info field from a given net state.
ls/2Query the list of tokens on the place named Place in the net instance identified as Name.
marking/1Query the marking map of the net instance identified as Name associating to each place name the list of tokens that this place holds.
reply/2Sends a reply to a calling client process.
reset_stats/1Requests the net instance identified as Name to clear its stats.
start_link/3Starts an unregistered net instance.
start_link/4Starts a net instance registered as ServerName using the callback module NetMod as the callback module for this net instance.
state_property/3Checks if a predicate about the state of the net holds.
stats/1Query the statistics gathered by the net instance identified as Name.
stop/1Requests the net instance identified as Name to stop.
usr_info/1Query the user info term from the net instance identified as Name.

Function Details

call/2

call(Name::name(), Request::term()) -> term()

Synchronously send the term Request to the net instance identified as Name and return the reply.

See also: call/3.

call/3

call(Name, Request, Timeout) -> term()

Synchronously send the term Request to the net instance identified as Name and return the reply.

The timeout is explicitly set to Timeout. The request is handled by the handle_call/3 callback function of the interface module. Herein Timeout must be a non-negative integer or the atom infinity.

cast/2

cast(Name::name(), Request::term()) -> ok

Asynchronously send the term Request to the net instance identified as Name.

The request is handled by the handle_cast/2 callback function of the interface module. Note that the cast succeeds even if a non-existing process is addressed or the net instance is down.

get_ls/2

get_ls(Place::atom(), NetState::#net_state{}) -> [term()]

Extracts the list of tokens on a given place from a given net state.

Throws an error if the list does not exist.

get_stats/1

get_stats(NetState::#net_state{}) -> #stats{}

Extracts the stats field from a given net instance.

get_usr_info/1

get_usr_info(NetState::#net_state{}) -> term()

Extracts the user info field from a given net state.

ls/2

ls(Name, Place) -> {ok, [term()]} | {error, #bad_place{}}

Query the list of tokens on the place named Place in the net instance identified as Name.

Herein, Name can be a process id or a registered process name. The return value is either {ok, [_]} if the place exists or a {error, #bad_place{}} tuple.

marking/1

marking(Name::name()) -> #{atom() => [term()]}

Query the marking map of the net instance identified as Name associating to each place name the list of tokens that this place holds.

Herein, Name can be a process id or a registered process name. The return value is the Petri net's marking map.

reply/2

reply(Client::{pid(), term()}, Reply::term()) -> term()

Sends a reply to a calling client process.

This funciton is to be used when the reply to a caller has been deferred by returning {noreply, _, _} in handle_call/3.

See also: handle_call/3.

reset_stats/1

reset_stats(Name::name()) -> ok

Requests the net instance identified as Name to clear its stats.

start_link/3

start_link(NetMod, NetArg, Options) -> start_link_result()

Starts an unregistered net instance.

See also: start_link/4.

start_link/4

start_link(ServerName, NetMod, InitArg, Options) -> start_link_result()

Starts a net instance registered as ServerName using the callback module NetMod as the callback module for this net instance.

The InitArg argument is later handed to the init/1 callback. The ServerName argument can be {local, Name} | {global, Name} | {via, Module, ViaName}. Internally, the server name ServerName and option list Options are handed down to gen_server:start_link/4 as is.

See also: init/1.

state_property/3

state_property(Name, Pred, PlaceLst) -> ok | {error, Reason}

Checks if a predicate about the state of the net holds.

The function takes a Petri net instance identified as Name and asks it to verify the predicate Pred over its marking. Herein, Pred is a function that takes n token lists, where each of the token lists subsume the tokens present on the places identified by the PlaceLst argument. The predicate is expected to return either ok or {error, Reason} where Reason can be any Erlang term.

stats/1

stats(Name::name()) -> #stats{}

Query the statistics gathered by the net instance identified as Name.

The throughput is given as a #stats{} record consisting of three #stat{} record instances characterizing the current, maximum, and minimum throughput of this net in transition firings per second.

stop/1

stop(Name::name()) -> ok

Requests the net instance identified as Name to stop.

usr_info/1

usr_info(Name::name()) -> term()

Query the user info term from the net instance identified as Name.


Generated by EDoc