<div class="gmail_quote">On Sun, Jan 31, 2010 at 4:09 PM, Robert Jacques <span dir="ltr">&lt;<a href="mailto:sandford@jhu.edu">sandford@jhu.edu</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div><div></div><div class="h5">On Sun, 31 Jan 2010 13:52:59 -0500, Kevin Bealer &lt;<a href="mailto:kevinbealer@gmail.com" target="_blank">kevinbealer@gmail.com</a>&gt; wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On Sun, Jan 31, 2010 at 7:51 AM, Michel Fortin &lt;<a href="mailto:michel.fortin@michelf.com" target="_blank">michel.fortin@michelf.com</a>&gt;wrote:<br>
...<br>
<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
Something &#39;unique&#39; is accessible through only one reference in the whole<br>
program, it is guarantied to have no aliasing. With &#39;lent&#39; you can lend a<br>
unique reference to a function: you know once it returns your reference is<br>
still unique. As long as this &#39;unique&#39; property holds, you can safely *move*<br>
the reference between threads. As long as the unique reference is kept<br>
thread-local you can access it without atomic operations or locks. &#39;unique&#39;<br>
can be seen as a temporary state as you can safely move it to immutable,<br>
mutable, shared, etc.<br>
<br>
Andrei wants to implement unique as a template, but it&#39;ll be very limited<br>
without &#39;lent&#39;. If I remember well, there&#39;s no general Unique template, just<br>
a UniqueArray for arrays of primitive types. Arrays of structs would allow<br>
taking the address of struct members and create aliasing.<br>
<br>
</blockquote>
<br>
I want to point out that this is only true if there is a memory barrier at<br>
the point of lending.  If object X belongs uniquely to thread 1, and it gets<br>
lent to thread 2, a memory barrier should happen at this point.  There are<br>
several cases where you can get hurt if this is not done:<br>
<br>
1. The object might have been owned by thread 2, then given to thread 1,<br>
which modified it, then returned to thread 2.  In this case, the second<br>
transfer is problematic because there might be a cached copy of the original<br>
in thread 2&#39;s L1 or L2 cache.<br>
<br>
2. The object might have been in the same cache line with another object<br>
that was modified, causing unintentional caching, and thus snapshotting a<br>
previous version of the object&#39;s state.<br>
<br>
3. Some other code might have fiddled with the object even though it is<br>
&#39;unique&#39; -- for example, the global garbage collector might have been run by<br>
thread 2, causing thread 2 to &quot;see&quot; a bunch of things that thread 1 thinks<br>
it uniquely owns.  This is going to be garbage collector design dependent,<br>
e.g. the GC might always do a memory barrier just before returning control<br>
to the user, in which case, no problem.<br>
<br>
The unique concept is a good thing but care must be taken -- I think<br>
Andrei&#39;s template version of the unique concept should be perfectly safe due<br>
to the fact that it does a copy.  It would be more efficient if a memory<br>
barrier could be used but that doesn&#39;t help with the analytical problem<br>
(making sure the old thread doesn&#39;t have a pointer stuck somewhere.)<br>
<br>
I just wanted to knock down what I think is a dangerous idea that some<br>
people might have inferred from the discussion on &#39;unique&#39; -- that thread X<br>
cannot have cached something if it was never &#39;seen&#39; by thread X before.  For<br>
that matter, I&#39;m not sure but without hard thread affinity, the CPU might<br>
have a cached version of something even if it the &#39;thread&#39; never saw it<br>
because the last thread to run there saw it.  (Or does thread switching<br>
always incur a memory barrier -- I don&#39;t know much about how that is usually<br>
done.)<br>
<br>
Kevin<br>
</blockquote>
<br></div></div>
This is a good point, but this has already been discussed and resolved in previous discussions. In essence, the all the ways for a unique object to move between threads involve memory barriers of their own which in turn protects the publication safety of both unique and immutable objects. As for the cache line issues, these are generally know as false sharing, and while they can be a major performance issue, they do not effect program correctness. Also, the problem with Andrei&#39;s library type is that it&#39;s shallow and not transitive. Lastly, lent doesn&#39;t refer to passing things between threads. It is like const, a super-type which allows a function to take a shared, local, owned or unique object in an agnostic manner, by providing the guarantee that it won&#39;t squirrel away (escape) it somewhere.<div>
<div></div><br></div></blockquote><div><br>Okay, I guess I missed or skimmed those discussions.  Thanks for the details.<br><br>Kevin<br><br></div></div>