%% -*- erlang -*- %% %% A generic Petri net OTP behavior. %% %% Copyright 2016-2017 Jorgen Brandt %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% ------------------------------------------------------------------- %% @author Jorgen Brandt %% @version 0.1.2 %% @copyright 2016-2017 Jorgen Brandt %% @doc Callback function definitions for Petri net actor interface. %% %% In addition to the structure callback functions there are another six %% 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 either generate a reply without %% changing the net marking by returning a `{reply, Reply}' tuple or it can %% generate a reply, consuming or producing tokens by returning a %% `{reply, Reply, ConsumeMap, ProduceMap}' tuple. %% %% Example: %% ``` %% handle_call( insert_coin, _, _ ) -> %% {reply, ok, #{}, #{ coin_slot => [coin] }}; %% %% handle_call( remove_cookie_box, _, %% #net_state{ marking = #{ compartment := C } } ) -> %% %% case C of %% [] -> {reply, {error, empty_compartment}}; %% [_|_] -> {reply, ok, #{ compartment => [cookie_box] }, #{}} %% end; %% %% handle_call( _, _, _ ) -> {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. %% %%

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/2

%% %% The `trigger/2' function determines what happens when a token is produced on %% a given place. Its first argument is the place name and its second argument %% is the token about to be produced. The `trigger/2' 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( _, _ ) -> pass. %% ''' %% Here, we simply let any token pass. %% %% @end %% ------------------------------------------------------------------- -module( gen_pnet_iface ). -include( "gen_pnet.hrl" ). -callback code_change( OldVsn :: _, NetState :: #net_state{}, Extra :: _ ) -> {ok, #net_state{}} | {error, _}. -callback handle_call( Request :: _, From :: {pid(), _}, NetState :: #net_state{} ) -> {reply, _} | {reply, _, #{ atom() => [_] }, #{ atom() => [_] }}. -callback handle_cast( Request :: _, NetState :: #net_state{} ) -> noreply | {noreply, #{ atom() => [_] }, #{ atom() => [_] }}. -callback handle_info( Info :: _, NetState :: #net_state{} ) -> noreply | {noreply, #{ atom() => [_] }, #{ atom() => [_] }}. -callback terminate( Reason :: _, NetState :: #net_state{} ) -> ok. -callback trigger( Place :: atom(), Token :: _ ) -> pass | drop.