public void ConcurrentGetOrAdd_ThreadSafeDictionary_Simplified()
        {
            // Without all the counters and boolean to validate the behaviour
            // The code is really simple
            var threadSafeDictionary = new ThreadSafeDictionary <long, string>();

            string Factory(long id)
            {
                switch (id)
                {
                case 1:
                    return("One");

                case 6:
                    return("Six");

                default:
                    throw new Exception("Not found");
                }
            };

            Parallel.For(
                0,
                50,
                i =>
            {
                var name = threadSafeDictionary.GetOrCreateValue(
                    6,
                    Factory);

                Assert.That(name, Does.StartWith("Six"));
            });
        }
        public void ConcurrentGetOrAdd_ThreadSafeDictionary()
        {
            // Some have even go further and have totally rewrite an alternative to ConcurrentDictionary
            // That takes all into account, to have something performant hen reading (no locks)
            // And without the flows of the ConcurrentDictionary
            // The code is really complex (see all what have been put in the Pfz folder),
            // but as you can see in that example the ThreadSafeDictionary seems to effectively do what we need,
            // and without having to wrap our factory into a Lazy wrapper
            // sources:
            // https://www.codeproject.com/Articles/548406/Dictionary-plus-Locking-versus-ConcurrentDictionar
            var threadSafeDictionary = new ThreadSafeDictionary <long, string>();

            var factoryCount   = 0;
            var exceptionCount = 0;

            Parallel.For(
                0,
                50,
                i =>
            {
                var added = false;

                string name;
                try
                {
                    name = threadSafeDictionary.GetOrCreateValue(
                        6,
                        n =>
                    {
                        added = true;
                        Interlocked.Increment(ref factoryCount);
                        Thread.Sleep(10);
                        if (factoryCount == 1)
                        {
                            throw new Exception("Issue while accessing a resource (network, file system, ...)");
                        }
                        return("Six" + "-from-" + i);
                    });
                }
                catch (Exception)
                {
                    Interlocked.Increment(ref exceptionCount);
                    return;
                }

                Assert.That(name, Does.StartWith("Six"));
                if (added)
                {
                    Assert.That(name, Does.EndWith("-from-" + i));
                }
                else
                {
                    Assert.That(name, Does.Not.EndWith("-from-" + i));
                }
            });

            Assert.That(factoryCount, Is.EqualTo(2));
            Assert.That(exceptionCount, Is.EqualTo(1));
        }
 public int GetOrCreate(int i)
 {
     return(_dictionary.GetOrCreateValue(i, _createValue));
 }