Skip to content

Commit

Permalink
new example: bank account
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielegenovese committed Feb 3, 2025
1 parent e31e468 commit 6235ce1
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 37 deletions.
17 changes: 17 additions & 0 deletions examples/account/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Dining example

## Use

```bash
./_build/default/bin/chorer ./examples/account/account.erl main/0 examples/account
```

## Description

Features:

- Show a deadlock

## Results

Good both LV and GV also with minimize.
23 changes: 23 additions & 0 deletions examples/account/account.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-module(account).
-export([main/0, account/1, client/1]).

main() ->
Acc = spawn(?MODULE, account, [1]),
spawn(?MODULE, client, [Acc]),
spawn(?MODULE, client, [Acc]).

account(Value) ->
receive
{get, P} ->
P ! Value,
account(value);
{set, NewValue} ->
account(NewValue)
end.

client(Account) ->
Account ! {get, self()},
receive
_Val -> do_something
end,
Account ! {set, 42}.
11 changes: 11 additions & 0 deletions examples/account/account_1_local_view.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
digraph account_1 {
rankdir="LR";
n_0 [label="account_1", shape="plaintext"];
n_1 [id="1", shape=circle, label="1"];
n_0 -> n_1 [arrowhead=none];
n_2 [id="2", shape=circle, label="2"];

n_2 -> n_1 [id="[$e|7]", label="P ! Value"];
n_1 -> n_1 [id="[$e|8]", label="1#receive {set,NewValue}"];
n_1 -> n_2 [id="[$e|0]", label="0#receive {get,P}"];
}
13 changes: 13 additions & 0 deletions examples/account/client_1_local_view.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
digraph client_1 {
rankdir="LR";
n_0 [label="client_1", shape="plaintext"];
n_1 [id="1", shape=circle, label="1"];
n_0 -> n_1 [arrowhead=none];
n_2 [id="4", shape=doublecircle, label="4"];
n_3 [id="3", shape=circle, label="3"];
n_4 [id="2", shape=circle, label="2"];

n_1 -> n_4 [id="[$e|0]", label="Account ! {get,pid_self}"];
n_4 -> n_3 [id="[$e|1]", label="0#receive _Val"];
n_3 -> n_2 [id="[$e|2]", label="Account ! {set,42}"];
}
73 changes: 73 additions & 0 deletions examples/account/main_0_global_view.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
digraph global {
rankdir="LR";
n_0 [label="global", shape="plaintext"];
n_1 [id="14", shape=circle, label="14"];
n_2 [id="28", shape=circle, label="28"];
n_3 [id="9", shape=circle, label="9"];
n_4 [id="26", shape=circle, label="26"];
n_5 [id="25", shape=circle, label="25"];
n_6 [id="8", shape=circle, label="8"];
n_7 [id="24", shape=circle, label="24"];
n_8 [id="17", shape=circle, label="17"];
n_9 [id="1", shape=circle, label="1"];
n_0 -> n_9 [arrowhead=none];
n_10 [id="7", shape=circle, label="7"];
n_11 [id="27", shape=circle, label="27"];
n_12 [id="16", shape=circle, label="16"];
n_13 [id="19", shape=circle, label="19"];
n_14 [id="4", shape=circle, label="4"];
n_15 [id="6", shape=circle, label="6"];
n_16 [id="3", shape=circle, label="3"];
n_17 [id="12", shape=circle, label="12"];
n_18 [id="18", shape=circle, label="18"];
n_19 [id="20", shape=circle, label="20"];
n_20 [id="23", shape=circle, label="23"];
n_21 [id="2", shape=circle, label="2"];
n_22 [id="22", shape=circle, label="22"];
n_23 [id="11", shape=circle, label="11"];
n_24 [id="15", shape=circle, label="15"];
n_25 [id="10", shape=circle, label="10"];
n_26 [id="13", shape=circle, label="13"];
n_27 [id="5", shape=circle, label="5"];
n_28 [id="21", shape=circle, label="21"];

n_15 -> n_3 [id="[$e|7]", label="client/1.0→account/1.0:{get,pid_self}"];
n_15 -> n_25 [id="[$e|8]", label="account/1.0→client/1.1:Value"];
n_7 -> n_11 [id="[$e|36]", label="client/1.1→account/1.0:{set,42}"];
n_1 -> n_28 [id="[$e|23]", label="client/1.1→account/1.0:{get,pid_self}"];
n_4 -> n_2 [id="[$e|38]", label="client/1.0→account/1.0:{set,42}"];
n_25 -> n_12 [id="[$e|16]", label="client/1.1→account/1.0:{set,42}"];
n_9 -> n_21 [id="[$e|0]", label="main/0.0Δaccount/1.0 args [1]"];
n_27 -> n_10 [id="[$e|5]", label="client/1.1→account/1.0:{get,pid_self}"];
n_6 -> n_26 [id="[$e|11]", label="client/1.1→account/1.0:{get,pid_self}"];
n_3 -> n_23 [id="[$e|13]", label="account/1.0→client/1.0:Value"];
n_10 -> n_23 [id="[$e|9]", label="account/1.0→client/1.0:Value"];
n_24 -> n_13 [id="[$e|24]", label="client/1.1→account/1.0:{set,42}"];
n_18 -> n_7 [id="[$e|28]", label="client/1.0→account/1.0:{set,42}"];
n_19 -> n_5 [id="[$e|31]", label="client/1.1→account/1.0:{set,42}"];
n_18 -> n_5 [id="[$e|29]", label="client/1.1→account/1.0:{set,42}"];
n_13 -> n_4 [id="[$e|30]", label="account/1.0→client/1.0:Value"];
n_22 -> n_4 [id="[$e|34]", label="account/1.0→client/1.0:Value"];
n_6 -> n_1 [id="[$e|12]", label="client/1.0→account/1.0:{set,42}"];
n_5 -> n_2 [id="[$e|37]", label="client/1.0→account/1.0:{set,42}"];
n_14 -> n_15 [id="[$e|4]", label="client/1.1→account/1.0:{get,pid_self}"];
n_20 -> n_11 [id="[$e|35]", label="client/1.1→account/1.0:{set,42}"];
n_14 -> n_27 [id="[$e|3]", label="client/1.0→account/1.0:{get,pid_self}"];
n_21 -> n_16 [id="[$e|1]", label="main/0.0Δclient/1.0 args [account/1.0]"];
n_23 -> n_8 [id="[$e|17]", label="client/1.0→account/1.0:{set,42}"];
n_12 -> n_22 [id="[$e|26]", label="client/1.0→account/1.0:{get,pid_self}"];
n_10 -> n_17 [id="[$e|10]", label="account/1.0→client/1.1:Value"];
n_16 -> n_14 [id="[$e|2]", label="main/0.0Δclient/1.1 args [account/1.0]"];
n_19 -> n_7 [id="[$e|32]", label="client/1.0→account/1.0:{set,42}"];
n_17 -> n_19 [id="[$e|20]", label="account/1.0→client/1.0:Value"];
n_24 -> n_19 [id="[$e|25]", label="account/1.0→client/1.0:Value"];
n_25 -> n_24 [id="[$e|15]", label="client/1.0→account/1.0:{get,pid_self}"];
n_17 -> n_13 [id="[$e|19]", label="client/1.1→account/1.0:{set,42}"];
n_28 -> n_20 [id="[$e|33]", label="account/1.0→client/1.1:Value"];
n_26 -> n_18 [id="[$e|22]", label="account/1.0→client/1.1:Value"];
n_27 -> n_6 [id="[$e|6]", label="account/1.0→client/1.0:Value"];
n_23 -> n_18 [id="[$e|18]", label="account/1.0→client/1.1:Value"];
n_8 -> n_20 [id="[$e|27]", label="account/1.0→client/1.1:Value"];
n_26 -> n_8 [id="[$e|21]", label="client/1.0→account/1.0:{set,42}"];
n_3 -> n_17 [id="[$e|14]", label="account/1.0→client/1.1:Value"];
}
13 changes: 13 additions & 0 deletions examples/account/main_0_local_view.dot
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
digraph main_0 {
rankdir="LR";
n_0 [label="main_0", shape="plaintext"];
n_1 [id="1", shape=circle, label="1"];
n_0 -> n_1 [arrowhead=none];
n_2 [id="4", shape=circle, label="3"];
n_3 [id="3", shape=doublecircle, label="4"];
n_4 [id="2", shape=circle, label="2"];

n_2 -> n_3 [id="[$e|0]", label="spawn client/1.1 args [account/1.0]"];
n_1 -> n_4 [id="[$e|1]", label="spawn account/1.0 args [1]"];
n_4 -> n_2 [id="[$e|2]", label="spawn client/1.0 args [account/1.0]"];
}
62 changes: 37 additions & 25 deletions src/choreography/gv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -465,36 +465,48 @@ get_local_vars(ProcId, Label, FunSName) ->
EM = db:get_lv_edge_additonal_info(element(1, remove_id_from_proc(ProcId))),
InputData = maps:get(Label, EM, []),
% log:debug("[GV] EmulProcName ~p Label ~p Input ~p~n", [FunSName, Label, EM]),
% add input data to local vars
% TODO: add input data to local vars
case InputData of
[] ->
[];
_ ->
[{_, Input}] = ets:lookup(?ARGUMENTS, share:atol(FunSName)),
% log:debug("[GV] for fun ~p found ~p~n", [share:atol(FunSName), Input]),
{LL, Remain} = lists:foldl(
fun({var, _, Name}, {A, In}) ->
case In of
[] ->
log:error("list should NOT be empty but there is ~p~n", Name),
{A ++ [#variable{name = Name}], []};
[H | T] ->
case H#variable.value of
"pid_self" ->
{A ++ [#variable{type = pid, name = Name, value = ProcId}], T};
_ ->
{A ++ [H#variable{name = Name}], T}
case ets:lookup(?ARGUMENTS, share:atol(FunSName)) of
[] ->
log:error("Cannot spawn process named", FunSName, []);
[{_, Input}] ->
% log:debug("[GV] for fun ~p found ~p~n", [share:atol(FunSName), Input]),
{LL, Remain} = lists:foldl(
fun({var, _, Name}, {A, In}) ->
case In of
[] ->
log:error("List should NOT be empty but there is ~p~n", Name),
{A ++ [#variable{name = Name}], []};
[H | T] ->
case H#variable.value of
"pid_self" ->
{
A ++
[
#variable{
type = pid, name = Name, value = ProcId
}
],
T
};
_ ->
{A ++ [H#variable{name = Name}], T}
end
end
end
end,
{[], InputData#variable.value},
Input
),
case Remain =:= [] of
true -> done;
false -> log:error("list should be empty but there is ~p~n", Remain)
end,
LL
end,
{[], InputData#variable.value},
Input
),
case Remain =:= [] of
true -> done;
false -> log:error("list should be empty but there is ~p~n", Remain)
end,
LL
end
end.

%%% Evaluate a send transition of an actor
Expand Down
10 changes: 4 additions & 6 deletions src/choreography/lv.erl
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,15 @@ create_localview(ActorName, StartingVars, SaveToFile) ->
RetLV =
case does_actor_exist(ActorName) of
false ->
io:fwrite(
"Critical error: Actor ~p's AST not found. Check the export attribute.~n", [
ActorName
]
),
log:error("[CRITICAL]: ~p's AST not found. Check the export attribute.~n", [
ActorName
]),
no_graph;
ActorAst ->
LV = db:get_localview(ActorName),
case LV of
not_found ->
io:fwrite("[LV] Creating a localview for ~p~n", [ActorName]),
log:info("[LV] Creating a localview for ~p~n", [ActorName]),
BaseData = #localview{
fun_name = ActorName, fun_ast = ActorAst, param = StartingVars
},
Expand Down
8 changes: 6 additions & 2 deletions src/share/log.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
warning/4,
warning/5,
error/2,
error/3
error/3,
inspect/1
]).

%%%===================================================================
Expand Down Expand Up @@ -38,5 +39,8 @@ warning(Package, String, Content, RetData, line) ->
error(String, Content) ->
io:fwrite("[ERROR]" ++ String, Content).
error(String, Content, RetData) ->
io:fwrite("ERROR: ~p ~p~n", [String, Content]),
io:fwrite("[ERROR] ~s ~p~n", [String, Content]),
RetData.

inspect(D) ->
io:fwrite("~p~n", [D]).
4 changes: 0 additions & 4 deletions src/share/share.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

%%% API
-export([
inspect/1,
first/1,
save_graph_to_file/4,
add_vertex/1,
Expand Down Expand Up @@ -39,9 +38,6 @@
first([]) -> [];
first([H | _]) -> H.

inspect(D) ->
io:fwrite("~p~n", [D]).

save_graph_to_file(Graph, Dir, FileName, Type) ->
StringName = format_name(FileName),
case Type of
Expand Down

0 comments on commit 6235ce1

Please sign in to comment.