Mark Elston (115) [Avatar] Offline
#1
At the start of section 2.3.2 you say: "But, it does not enforce the function initializer func(a) from being executed multiple times for the same value, while evaluating the expression."

I don't understand this. The initializer function is only called if the value is not found in the cache, right? So why would it ever be called multiple times for the same value?
Riccardo Terrell (16) [Avatar] Offline
#2
Thanks for the question.
In the example that you are pointing out, the Memoization function is implemented using a ConcurrentDictionary as form of defense against possible race-condition.

public static Func<a, b> Memoize<a, b>(this Func<a, b> func)
{
    var cache = new ConcurrentDictionary<a, b>();
    return a => cache.GetOrAdd(a, func);
};


However, according with the Microsoft documentation, the method GetOrAdd does not prevent the function `func` from being called more than once for the same given argument, but it does guarantee that the result of only one “evaluation of the function” is actually added to the collection. For example, there could be multiple threads checking the cache concurrently before the cached value is actually added.
Moreover, there is no way to enforce the function `func(a)` to be thread-safe, in fact, without this guarantee, it is possible that in a multithreaded environment, multiple threads could access the same function simultaneously. Ergo, the ` func(a) ` should also be thread-safe itself. The solution proposed, avoiding primitive locks, is to use the Lazy<T> construct in .NET 4.0. This solution gives you both the guarantee of full thread safety, regardless the implementation of the function `func`, and ensures a single evaluation of the function.

public static Func<a, b> Memoize<a, b>(this Func<a, b> func)
{
    var cache = new ConcurrentDictionary<a, b>();
    return a => cache.GetOrAdd(a, new Lazy<a>(() => func(a), LazyExecutionMode.EnsureSingleThreadSafeExecution)).Value;
};


please let me know if this is clear, I will put a note to add further explanation in the section.
Mark Elston (115) [Avatar] Offline
#3
Thanks. I think that explains it pretty well.
Riccardo Terrell (16) [Avatar] Offline
#4
Cool!! I will reformulate and update the chapter to make it more clear.
Thanks for the feedback... and keep going smilie