Copyright (c) 2016 Guilherme Andrade
Version: 1.1.2
Authors: Guilherme Andrade (nlocks(at)gandrade(dot)net
).
nlocks
: Native spinlocks for Erlang
An experiment on Erlang native spinlocks:
Lock = nlocks:new(),
Transaction = fun() ->
io:format("hello from ~p at ~p~n", [self(), os:timestamp()]),
timer:sleep(100)
end,
[spawn(fun () -> nlocks:transaction(Lock, Transaction) end) || _ <- lists:seq(1, 4)].
% hello from <0.66.0> at {1465,509871,454813}
% hello from <0.69.0> at {1465,509871,555028}
% hello from <0.67.0> at {1465,509871,656021}
% hello from <0.68.0> at {1465,509871,757031}
Hackish solution. Other than setting up some sort of monitor in the Erlang land, I found no practical way to deal with these other than making use of ownership objects, references to which should never leave the process under which they were created; the release therefore becomes dependent on the garbage collector calling their destructor, but this also makes it more convenient for regularly terminated processes that forget to clean up.
struct Ownership {
ERL_NIF_TERM pid;
Lock** lockResource;
};
struct Lock {
std::atomic<Ownership*> ownership;
};
% nlocks:info()
[{allocated_locks,2},
{allocated_ownerships,6},
{acquired_locks,1},
{contention,5}, % amount of processes attempting lock acquisition
{has_lockfree_counters,true},
{has_lockfree_ownership,true}]
nlocks |