{"id":55925,"date":"2010-04-12T10:00:00","date_gmt":"2010-04-12T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2010\/04\/12\/parallelextensionsextras-tour-8-reductionvariablet\/"},"modified":"2010-04-12T10:00:00","modified_gmt":"2010-04-12T10:00:00","slug":"parallelextensionsextras-tour-8-reductionvariablet","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/parallelextensionsextras-tour-8-reductionvariablet\/","title":{"rendered":"ParallelExtensionsExtras Tour &#8211; #8 &#8211; ReductionVariable"},"content":{"rendered":"<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\"><em>(The full set of ParallelExtensionsExtras Tour posts is available&nbsp;<\/em><a href=\"https:\/\/blogs.msdn.com\/pfxteam\/archive\/2010\/04\/04\/9990342.aspx\"><font color=\"#dd4a21\"><em>here<\/em><\/font><\/a><em>.)<\/em>&nbsp;<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The new .NET 4 System.Threading.<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd642243(VS.100).aspx\">ThreadLocal&lt;T&gt;<\/a> is quite useful when you need per-thread, per-instance storage.<span>&nbsp; <\/span>This is in contrast to the fast ThreadStaticAttribute, which supports only per-thread storage (in .NET 4, ThreadLocal&lt;T&gt; actually layers on top of ThreadStaticAttribute to provide the additional per-instance behavior).<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">ThreadLocal&lt;T&gt; exposes through its Value property the thread-local value of the variable for the current thread.<span>&nbsp; <\/span>However, it doesn&rsquo;t expose in any way a collection of all of the thread-local values that have been created on that ThreadLocal&lt;T&gt; instance.<span>&nbsp; <\/span>Having that functionality can be useful in a variety of circumstances.<span>&nbsp; <\/span>For example, if you use ThreadLocal&lt;T&gt; to store per-thread instances of some heavyweight and disposable object, you might want to dispose of all of the instances when you&rsquo;re done using them.<span>&nbsp; <\/span>Or if you were implementing a reduction, doing a local reduction on each thread involved in the computation, you would need access to all of the thread-local values at the end in order to do the final cross-thread reduction.<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">This extra functionality is quite similar to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd492850(VS.100).aspx\">combinable<\/a> type provided in Visual C++ 10.<span>&nbsp; <\/span>And although ThreadLocal&lt;T&gt; doesn&rsquo;t provide this functionality out-of-the-box, we can easily layer it on top of it.<span>&nbsp; <\/span>This is precisely what the ReductionVariable&lt;T&gt; type in <a href=\"https:\/\/code.msdn.microsoft.com\/ParExtSamples\">ParallelExtensionsExtras<\/a> provides (see the ReductionVariable.cs file).<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The ReductionVariable&lt;T&gt; type is very similar to ThreadLocal&lt;T&gt; in surface area, the key difference being that it adds a Values property (plural)&nbsp;that&rsquo;s an IEnumerable&lt;T&gt; in addition to exposing the familiar Value property (singular) that returns a T:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">public sealed class ReductionVariable&lt;T&gt;<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">{<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>public ReductionVariable(Func&lt;T&gt; seedFactory);<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>public T Value { get; }<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;<\/span><span>&nbsp;&nbsp; <\/span>public IEnumerable&lt;T&gt; Values { get; }<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>&#8230; \/\/ a few additional public helper methods<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">}<\/p>\n<p><\/font><\/p>\n<p class=\"Code\">\n<p><font face=\"Consolas\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The ReductionVariable&lt;T&gt; instance maintains three private fields:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">private readonly Func&lt;T&gt; _seedFactory;<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">private readonly ThreadLocal&lt;StrongBox&lt;T&gt;&gt; _threadLocal;<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">private readonly ConcurrentQueue&lt;StrongBox&lt;T&gt;&gt; _values;<\/p>\n<p><\/font><\/p>\n<p class=\"Code\">\n<p><font face=\"Consolas\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The Func&lt;&gt; is the user-provided delegate used to initialize a thread&rsquo;s local value when one hasn&rsquo;t been initialized yet (if the seed factory is null, the default value of T will be used).<span>&nbsp; <\/span>The ThreadLocal&lt;&gt; is the thread-local storage, and the ConcurrentQueue&lt;&gt; is used to store all of the values from all of the threads.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">Because we need to maintain a list of all of the thread-local values, and because the thread-local values might change over time, we need to wrap the values with an object we can always use to reference each of them.<span>&nbsp; <\/span>For that purpose, we utilize the System.Runtime.CompilerServices.StrongBox&lt;T&gt; type, which is simply an object that contains a field of type T.<span>&nbsp; <\/span>Then, instead of using a ThreadLocal&lt;T&gt;, we utilize a ThreadLocal&lt;StrongBox&lt;T&gt;&gt;, and instead of using a ConcurrentQueue&lt;T&gt;, we use a ConcurrentQueue&lt;StrongBox&lt;T&gt;&gt;.<span>&nbsp; <\/span>In this manner, the Value field of the StrongBox instances may change repeatedly, but the StrongBox&lt;T&gt; object reference will remain constant.<span>&nbsp; <\/span>From this, the rest of the implementation falls into place.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The constructor initializes the ThreadLocal&lt;StrongBox&lt;T&gt;&gt; to create a StrongBox&lt;T&gt; that wraps a newly created seed value and adds that new StrongBox&lt;T&gt; instance to the queue of values.<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">public ReductionVariable(Func&lt;T&gt; seedFactory)<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">{<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>_seedFactory = seedFactory;<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>_threadLocal = new ThreadLocal&lt;StrongBox&lt;T&gt;&gt;(CreateValue);<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">}<\/p>\n<p><\/font><\/p>\n<p class=\"Code\">\n<p><font face=\"Consolas\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"Code\"><font face=\"Consolas\">private StrongBox&lt;T&gt; CreateValue()<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">{<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>var s = new StrongBox&lt;T&gt;(<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>_seedFactory != null ? _seedFactory() : default(T));<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>_values.Enqueue(s);<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>return s;<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">}<\/p>\n<p><\/font><\/p>\n<p class=\"Code\">\n<p><font face=\"Consolas\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">The Value property then need only get and set the boxed value&rsquo;s value:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">public T Value<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">{<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>get { return _threadLocal.Value.Value; }<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>set { _threadLocal.Value.Value = value; }<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">}<\/p>\n<p><\/font><\/p>\n<p class=\"Code\">\n<p><font face=\"Consolas\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">And the Values property need only return the contents of the list.<span>&nbsp; <\/span>Of course, we don&rsquo;t want to return the StrongBox&lt;T&gt; instances, but rather the values they contain, so we&rsquo;ll use LINQ&#8217;s Select method to select just the values:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">public IEnumerable&lt;T&gt; Values <\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">{ <\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>get { return _values.Select(s =&gt; s.Value); } <\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">}<\/p>\n<p><\/font><\/p>\n<p class=\"Code\">\n<p><font face=\"Consolas\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font size=\"3\"><font face=\"Calibri\">With our ReductionVariable&lt;T&gt; in place, we can now utilize it to perform reductions, to track and clean up after thread-local state, and more.<span>&nbsp; <\/span>Here&rsquo;s an example:<\/p>\n<p><\/font><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">var edos = new ReductionVariable&lt;ExpensiveDisposableObject&gt;(<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp; <\/span>() =&gt; new ExpensiveDisposableObject());<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">var q = (from d in dataSource.AsParallel<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>select ProcessValueWithExpensiveObject(d, edos.Value)).ToArray();<\/p>\n<p><\/font><\/p>\n<p class=\"Code\"><font face=\"Consolas\">foreach(var edo in edos) edo.Dispose();<\/p>\n<p><\/font><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>(The full set of ParallelExtensionsExtras Tour posts is available&nbsp;here.)&nbsp; The new .NET 4 System.Threading.ThreadLocal&lt;T&gt; is quite useful when you need per-thread, per-instance storage.&nbsp; This is in contrast to the fast ThreadStaticAttribute, which supports only per-thread storage (in .NET 4, ThreadLocal&lt;T&gt; actually layers on top of ThreadStaticAttribute to provide the additional per-instance behavior). ThreadLocal&lt;T&gt; exposes through [&hellip;]<\/p>\n","protected":false},"author":360,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[7907,7911,7916,7909,7924],"class_list":["post-55925","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam","tag-net-4","tag-code-samples","tag-coordination-data-structures","tag-parallel-extensions","tag-parallelextensionsextras"],"acf":[],"blog_post_summary":"<p>(The full set of ParallelExtensionsExtras Tour posts is available&nbsp;here.)&nbsp; The new .NET 4 System.Threading.ThreadLocal&lt;T&gt; is quite useful when you need per-thread, per-instance storage.&nbsp; This is in contrast to the fast ThreadStaticAttribute, which supports only per-thread storage (in .NET 4, ThreadLocal&lt;T&gt; actually layers on top of ThreadStaticAttribute to provide the additional per-instance behavior). ThreadLocal&lt;T&gt; exposes through [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55925","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/360"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=55925"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/55925\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=55925"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=55925"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=55925"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}