Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uw general improvements #41

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
deps
*.o
*.beam
*.plt
*.plt
_build
.rebar3
*.[eh]rl~
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions examples/gdict/src/gdict.app.src
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{application, gdict,
[
{description, ""},
{vsn, "1"},
{registered, []},
{applications, [
kernel,
stdlib,
locks
]},
{mod, []},
{env, []}
]}.
File renamed without changes.
47 changes: 29 additions & 18 deletions examples/src/gdict.erl → examples/gdict/src/gdict.erl
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ trace(F) when is_function(F, 0) ->
F().

new() ->
locks_leader:start_link(test_cb, dict:new()).
locks_leader:start_link(test_cb, #{}).

new(Name) ->
locks_leader:start_link(Name, test_cb, dict:new(), []).
locks_leader:start_link(Name, test_cb, #{}, []).

new_opt(Opts) ->
locks_leader:start_link(test_cb, dict:new(), Opts).
locks_leader:start_link(test_cb, #{}, Opts).

-define(store(Dict,Expr,Legend),
locks_leader:leader_call(Dict, {store, fun(D) ->
Expand All @@ -84,27 +84,38 @@ new_opt(Opts) ->

%% dict functions that modify state:
append(Key, Value, Dict) ->
?store(Dict, dict:append(Key,Value,D), append).
?store(Dict, maps_append(Key,Value,D), append).
append_list(Key, ValList, Dict) ->
?store(Dict, dict:append_list(Key,ValList,D), append_list).
?store(Dict, maps_append_list(Key,ValList,D), append_list).
erase(Key, Dict) ->
?store(Dict, dict:erase(Key,D), erase).
?store(Dict, maps:remove(Key,D), erase).
store(Key, Value, Dict) ->
?store(Dict, dict:store(Key,Value,D), store).
?store(Dict, maps:put(Key,Value,D), store).
update(Key,Function,Dict) ->
?store(Dict, dict:update(Key,Function,D), update).
?store(Dict, maps:update_with(Key,Function,D), update).
update(Key, Function, Initial, Dict) ->
?store(Dict, dict:update(Key,Function,Initial,D), update).
?store(Dict, maps:update_with(Key,Function,Initial,D), update).
update_counter(Key, Incr, Dict) ->
?store(Dict, dict:update_counter(Key,Incr,D), update_counter).
?store(Dict, maps_update_counter(Key,Incr,D), update_counter).

%% dict functions that do not modify state (lookup functions)
%%
fetch(Key, Dict) -> ?lookup(Dict, dict:fetch(Key,D), fetch).
fetch_keys(Dict) -> ?lookup(Dict, dict:fetch_keys(D), fetch_keys).
filter(Pred, Dict) -> ?lookup(Dict, dict:filter(Pred,D), filter).
find(Key, Dict) -> ?lookup(Dict, dict:find(Key,D), find).
fold(Fun, Acc0, Dict) -> ?lookup(Dict, dict:fold(Fun,Acc0,D), fold).
is_key(Key, Dict) -> ?lookup(Dict, dict:is_key(Key,D), is_key).
map(Fun, Dict) -> ?lookup(Dict, dict:map(Fun,D), map).
to_list(Dict) -> ?lookup(Dict, dict:to_list(D), to_list).
fetch(Key, Dict) -> ?lookup(Dict, maps:get(Key,D), fetch).
fetch_keys(Dict) -> ?lookup(Dict, maps:keys(D), fetch_keys).
filter(Pred, Dict) -> ?lookup(Dict, maps:filter(Pred,D), filter).
find(Key, Dict) -> ?lookup(Dict, maps:find(Key,D), find).
fold(Fun, Acc0, Dict) -> ?lookup(Dict, maps:fold(Fun,Acc0,D), fold).
is_key(Key, Dict) -> ?lookup(Dict, maps:is_key(Key,D), is_key).
map(Fun, Dict) -> ?lookup(Dict, maps:map(Fun,D), map).
to_list(Dict) -> ?lookup(Dict, maps:to_list(D), to_list).

maps_append(Key, Value, D) ->
maps_append_list(Key, [Value], D).

maps_append_list(Key, ValList, D) ->
L = maps:get(Key, D, []),
D#{Key => L ++ ValList}.

maps_update_counter(Key, Incr, D) ->
Old = maps:get(Key, D, 0),
D#{Key => Old + Incr}.
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ merge_dicts(D, I) ->
lists:foldl(
fun({C, {true, D2}}, Acc) ->
?event({merge_got, C, D2}),
dict:merge(fun(_K,V1,_) -> V1 end, Acc, D2);
maps:merge(Acc, D2); %% our content takes priority
({C, false}, Acc) ->
?event({merge_got, C, false}),
Acc
Expand Down
14 changes: 8 additions & 6 deletions include/locks.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,20 @@
-type agent() :: pid().
-type tid() :: any().

-type lock_id() :: {oid(), node()}.
-type lock_id() :: {oid() | '_', node()}.

-type obj() :: {oid(), mode()}
| {oid(), mode(), where()}
| {oid(), mode(), where(), req()}.

-type objs() :: [obj()].

-type options() :: [{link, boolean()}
| {client, pid()}
| {abort_on_error, boolean()}
| {abort_on_deadlock, boolean()}].
-type options() :: [option()].
-type option() :: {link, boolean()}
| {client, pid()}
| {abort_on_error, boolean()}
| {await_nodes, boolean()}
| {abort_on_deadlock, boolean()}.

-type deadlocks() :: [lock_id()].

Expand Down Expand Up @@ -60,7 +62,7 @@
version = 1 :: integer() | '_',
pid = self() :: pid() | '_',
queue = [] :: [#r{} | #w{}] | '_',
watchers = [] :: [pid()]
watchers = [] :: [pid()] | '_'
}).

-record(locks_info, {
Expand Down
7 changes: 3 additions & 4 deletions rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
{app_default, "http://www.erlang.org/doc/man"},
{doc_path, []},
{top_level_readme,
{"./README.md","https://github.com/uwiger/locks"}}]}]}

{"./README.md","https://github.com/uwiger/locks"}}]}
]},
{test, [{project_app_dirs, [".", "examples/gdict"]}]}
]}.

{ct_opts, [{dir, ["test", "examples/src"]}]}.
8 changes: 8 additions & 0 deletions rebar.config.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
%% -*- mode:erlang; erlang-indent-level:4; indent-tabs-mode:nil -*-
case os:getenv("LOCKS_DEBUG") of
false ->
CONFIG;
S when S =/= "false" ->
io:fwrite("Enabling runtime debugging~n", []),
[{erl_opts, [{d,'LOCKS_DEBUG'}]} | CONFIG]
end.
6 changes: 6 additions & 0 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"1.1.0",
[{<<"plain_fsm">>,{pkg,<<"plain_fsm">>,<<"1.4.1">>},0}]}.
[
{pkg_hash,[
{<<"plain_fsm">>, <<"47E9BF6AC9322FC7586FB6DF8DE7198391E93764571C75165F2C45B27ACDE1D0">>}]}
].
19 changes: 19 additions & 0 deletions src/locks.erl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
lock_nowait/4,
lock_objects/2, %% (Agent, Objects)
await_all_locks/1, %% (Agent)
transaction_status/1, %% (Agent)
watch/2, %% (OID, Nodes)
unwatch/2, %% (OID, Nodes)
watchers/1, %% (OID)
Expand Down Expand Up @@ -191,6 +192,24 @@ lock_objects(Agent, Objects) ->
await_all_locks(Agent) ->
locks_agent:await_all_locks(Agent).

%% @doc Inquire about the current status of the transaction.
%% Return values:
%% <dl>
%% <dt>`no_locks'</dt>
%% <dd>No locks have been requested</dd>
%% <dt>`{have_all_locks, Deadlocks}'</dt>
%% <dd>All requested locks have been claimed, `Deadlocks' indicates whether
%% any deadlocks were resolved in the process.</dd>
%% <dt>`waiting'</dt>
%% <dd>Still waiting for some locks.</dd>
%% <dt>`{cannot_serve, Objs}'</dt>
%% <dd>Some lock requests cannot be served, e.g. because some nodes are
%% unavailable.</dd>
%% </dl>
%% @end
transaction_status(Agent) ->
locks_agent:transaction_status(Agent).

-spec watch(oid(), [node()]) -> ok.
%% @doc Subscribe to lock state changes.
%%
Expand Down
Loading