From 6381f3eeeb4b759e56c917437964fd882c2a8efb Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Laval?= Date: Tue, 24 Aug 2010 17:35:19 +0100 Subject: [PATCH] Correctly support calling lazily factory lambdas in ConcurrentDictionary. --- .../ConcurrentDictionary.cs | 4 +- .../SplitOrderedList.cs | 61 +++++++------------ 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs b/mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs index 25dd6e5667e..40984d16e55 100644 --- a/mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs +++ b/mcs/class/corlib/System.Collections.Concurrent/ConcurrentDictionary.cs @@ -151,12 +151,12 @@ namespace System.Collections.Concurrent public TValue GetOrAdd (TKey key, Func valueFactory) { - return internalDictionary.InsertOrGet (Hash (key), Make (key, valueFactory (key))).Value; + return internalDictionary.InsertOrGet (Hash (key), Make (key, default(TValue)), () => Make (key, valueFactory (key))).Value; } public TValue GetOrAdd (TKey key, TValue value) { - return GetOrAdd (key, (_) => value); + return internalDictionary.InsertOrGet (Hash (key), Make (key, value), null).Value; } public bool TryRemove (TKey key, out TValue value) diff --git a/mcs/class/corlib/System.Collections.Concurrent/SplitOrderedList.cs b/mcs/class/corlib/System.Collections.Concurrent/SplitOrderedList.cs index 3fd7e5226aa..58b913734b0 100644 --- a/mcs/class/corlib/System.Collections.Concurrent/SplitOrderedList.cs +++ b/mcs/class/corlib/System.Collections.Concurrent/SplitOrderedList.cs @@ -44,43 +44,22 @@ namespace System.Collections.Concurrent class Node { - bool marked; - uint key; - T data; + public readonly bool Marked; + public readonly uint Key; + public T Data; public Node Next; public Node (uint key, T data) : this (false) { - this.key = key; - this.data = data; + this.Key = key; + this.Data = data; } protected Node (bool marked) { - this.marked = marked; - } - - public bool Marked { - get { - return marked; - } - } - - public uint Key { - get { - return key; - } - } - - public T Data { - get { - return data; - } - set { - data = value; - } + this.Marked = marked; } } @@ -125,44 +104,44 @@ namespace System.Collections.Concurrent public T InsertOrUpdate (uint key, Func addGetter, Func updateGetter) { Node current; - T data = addGetter (); - bool result = InsertInternal (key, data, out current); + bool result = InsertInternal (key, default (T), addGetter, out current); if (result) - return data; + return current.Data; + // FIXME: this should have a CAS-like behavior return current.Data = updateGetter (current.Data); } public bool Insert (uint key, T data) { Node current; - return InsertInternal (key, data, out current); + return InsertInternal (key, data, null, out current); } - public T InsertOrGet (uint key, T data) + public T InsertOrGet (uint key, T data, Func dataCreator) { Node current; - if (!InsertInternal (key, data, out current)) - return current.Data; - - return data; + InsertInternal (key, data, dataCreator, out current); + return current.Data; } - bool InsertInternal (uint key, T data, out Node current) + bool InsertInternal (uint key, T data, Func dataCreator, out Node current) { Node node = new Node (ComputeRegularKey (key), data); uint b = key % (uint)size; if (GetBucket (b) == null) InitializeBucket (b); - if (!ListInsert (node, GetBucket (b), out current)) + if (!ListInsert (node, GetBucket (b), out current, dataCreator)) return false; int csize = size; if (Interlocked.Increment (ref count) / csize > MaxLoad) Interlocked.CompareExchange (ref size, 2 * csize, csize); + current = node; + return true; } @@ -238,7 +217,7 @@ namespace System.Collections.Concurrent InitializeBucket ((uint)parent); Node dummy = new Node (ComputeDummyKey (b), default (T)); - if (!ListInsert (dummy, GetBucket (parent), out current)) + if (!ListInsert (dummy, GetBucket (parent), out current, null)) dummy = current; SetBucket (b, dummy); @@ -385,7 +364,7 @@ namespace System.Collections.Concurrent return true; } - bool ListInsert (Node newNode, Node startPoint, out Node current) + bool ListInsert (Node newNode, Node startPoint, out Node current, Func dataCreator) { uint key = newNode.Key; Node rightNode = null, leftNode = null; @@ -396,6 +375,8 @@ namespace System.Collections.Concurrent return false; newNode.Next = rightNode; + if (dataCreator != null) + newNode.Data = dataCreator (); if (Interlocked.CompareExchange (ref leftNode.Next, newNode, rightNode) == rightNode) return true; } while (true); -- 2.25.1