<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>nlocks</title>
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc">
</head>
<body bgcolor="white">
<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
<h1>nlocks</h1>
<p>Copyright © 2016 Guilherme Andrade</p>
<p><b>Version:</b> 1.1.2</p>
<p><b>Authors:</b> Guilherme Andrade (<a href="mailto:nlocks(at)gandrade(dot)net"><tt>nlocks(at)gandrade(dot)net</tt></a>).</p>
<p><code>nlocks</code>: Native spinlocks for Erlang</p>

<hr>

<p>An experiment on Erlang native spinlocks:
* Able to guarantee exclusive access to shared resources
* Not dependent on a single process (no flooded mailbox as a bottleneck)
* Able to deal with brutally killed processes that still held unreleased locks (more below)</p>

<pre lang="erlang">
Lock = nlocks:new(),
Transaction = fun() -&gt;
    io:format("hello from ~p at ~p~n", [self(), os:timestamp()]),
    timer:sleep(100)
end,

[spawn(fun () -&gt; nlocks:transaction(Lock, Transaction) end) || _ &lt;- lists:seq(1, 4)].
% hello from &lt;0.66.0&gt; at {1465,509871,454813}
% hello from &lt;0.69.0&gt; at {1465,509871,555028}
% hello from &lt;0.67.0&gt; at {1465,509871,656021}
% hello from &lt;0.68.0&gt; at {1465,509871,757031}
</pre>

<h3><a name="Brutal_kills_and_unreleased_locks">Brutal kills and unreleased locks</a></h3><p>
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.</p>

<h3><a name="Ownership_objects">Ownership objects</a></h3>
<pre lang="c++">
struct Ownership {
    ERL_NIF_TERM pid;
    Lock** lockResource;
};
</pre>

<p>* They're created for lock acquisition in order to deal with the above problem
* They should never leave their owning process
* On successful acquisition, they link themselves to the lock and force it to live as long as they live
* They guarantee only the lock owner can release the lock
* No explicit destruction needed</p>

<h3><a name="Lock_objects">Lock objects</a></h3>
<pre lang="c++">
struct Lock {
    std::atomic&lt;Ownership*&gt; ownership;
};
</pre>

<p>* They keep an atomic pointer either set to null (free) or to the ownership object's address (locked)
* Can be shared between local processes through messages, ETS tables, etc.
* No explicit destruction needed</p>

<h3><a name="The_spinning">The spinning</a></h3><p>
* It uses C++ 11 <a href="http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange">compare_exchange_weak</a>
* For each attempt, a new NIF call is scheduled; this brings some overhead to the table but it's crucial to play nice with the VM
* If the timeout is other than 'infinity', for each attempt it compares the deadline against the current <a href="http://en.cppreference.com/w/cpp/chrono/steady_clock">steady_clock</a> value; this feels excessive and might hurt performance.</p>

<h3><a name="Internal_metrics">Internal metrics</a></h3>
<pre lang="erlang">
% 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}]
</pre>

<hr>
<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div>
<p><i>Generated by EDoc, May 1 2017, 02:21:31.</i></p>
</body>
</html>
