Tuesday, May 29, 2012

Dictionary is not thread safe

No surprises, dictionary is not thread safe.  But what if you're using it with guaranteed unique keys; ie each thread is guaranteed to be accessing it with a key unique to only that thread?

Here's a test:


private static readonly Dictionary<string, string> dictionary = new Dictionary<string, string>();

     public static void Main(string[] args)
        {
            var threads = new List<Thread>();
            for (int threadNumber = 0; threadNumber < 100; threadNumber++)
            {
                int number = threadNumber;
                var thread = new Thread(
                    () =>
                    {
                        for (int index = 0; index < 1000; index++)
                        {
                            Console.WriteLine("Thread" + number + " index " + index);
                            var key = Guid.NewGuid().ToString();
                            dictionary.Add(key, "Value");
                            var dynamicValue = Guid.NewGuid().ToString();
                            dictionary[key] = dynamicValue;
                            Debug.Assert(dictionary[key] == dynamicValue);
                        }
                    });
                threads.Add(thread);
                thread.Start();
            }

            foreach (var thread in threads)
            {
                thread.Join();
            }
        }

So, as you can see, this is creating a bunch of threads that all hammer the dictionary adding and editing and then asserting everything is as it should be. This runs fine with no exceptions. Or does it...

Comment the Console.WriteLine and it no longer runs...


So what is happening here?  As the dictionary gets larger the it will need to change its internal storage to increase its size, when this occurs another thread will either corrupt it or access stale data. So bad news.

The morale of the story is always add a Console.WriteLine before accessing a dictionary. Just kidding. If you think there will be any sort of multi-thread contention use a ConcurrentDictionary instead.  Just simply by thinking each thread accessing the dictionary using a guaranteed unique key will not suffice.

Sunday, May 6, 2012

Version 1.0.16 of Type Visualiser

A new version of Type Visualiser is available. See the Type Visualiser page for download details.

I've added a new mulit-document interface using tabs to allow many diagrams to be open at once.  I found this is need when using the tool for any serious discovery of unfamilar code.


Unlike the standard WPF tab control I have written my own to ensure individual tabs are kept in memory for fast switching between tabs.  This will consume memory the more tabs you open, but waiting between tab switch didn't feel like a good user experience.  As types are loaded they are also stored in a global cache to prevent analysing the same type twice even for different diagrams.  

I'm currently looking at changing the way I've implemented zooming, panning and centreing to a far better approach. This will allow for animations when zooming and for infinite canvas size that expands when diagrams push the boundaries of the diagram.

Enjoy.

Thursday, April 12, 2012

ReadOnlyDictionary Template

A re-usable template for a read only dictionary.
Edit: I changed Keys and Values collection to IEnumerable. Previously it was ICollection which has a Remove and Add method.

public interface IReadOnlyDictionary<TKey, TValue>
    {
        bool ContainsKey(TKey key);

        IEnumerable<TKey> Keys { get; }
        
        IEnumerable<TValue> Values { get; }
        
        int Count { get; }
        
        bool IsReadOnly { get; }
        
        bool TryGetValue(TKey key, out TValue value);
        
        TValue this[TKey key] { get; }
        
        bool Contains(KeyValuePair<TKey, TValue> item);
        
        void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex);
        
        IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator();
    }

    public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>
    {
        private readonly IDictionary<TKey, TValue> dictionary;

        public ReadOnlyDictionary()
        {
            this.dictionary = new Dictionary<TKey, TValue>();
        }

        public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary)
        {
            this.dictionary = dictionary;
        }

        public void Add(TKey key, TValue value)
        {
            throw new NotSupportedException("This dictionary is read-only");
        }

        public bool ContainsKey(TKey key)
        {
            return this.dictionary.ContainsKey(key);
        }

        public ICollection<TKey> Keys
        {
            get
            {
                return this.dictionary.Keys;
            }
        }

        public bool Remove(TKey key)
        {
            throw new NotSupportedException("This dictionary is read-only");
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            return this.dictionary.TryGetValue(key, out value);
        }

        public ICollection<TValue> Values
        {
            get
            {
                return this.dictionary.Values;
            }
        }

        public TValue this[TKey key]
        {
            get
            {
                return this.dictionary[key];
            }
            set
            {
                throw new NotSupportedException("This dictionary is read-only");
            }
        }

        public void Add(KeyValuePair<TKey, TValue> item)
        {
            throw new NotSupportedException("This dictionary is read-only");
        }

        public void Clear()
        {
            throw new NotSupportedException("This dictionary is read-only");
        }

        public bool Contains(KeyValuePair<TKey, TValue> item)
        {
            return this.dictionary.Contains(item);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            this.dictionary.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get
            {
                return this.dictionary.Count;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return true;
            }
        }

        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            throw new NotSupportedException("This dictionary is read-only");
        }

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return this.dictionary.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (this.dictionary as System.Collections.IEnumerable).GetEnumerator();
        }
    }

Sunday, April 8, 2012

Using the Factory Method Pattern

The factory method pattern is a creational software design pattern that encapsulates how to construct a dependency into method.  The method could return any number of concrete implementations. However the consuming code only accesses the dependency through an interface or abstract base class.  This pattern is useful when there is distinct logic to return one concrete class over another.  It is also an effective pattern when working with legacy code, as it is easier to introduce a new method than a whole new interface.

The essence of the pattern is simply a virtual method that contains logic to create and/or return an instance of a dependency used by the consuming class.

Here's an example using the pattern to allow for unit testing substitution.


namespace FactoryMethodDemo
{
    public class ProductMaintenance
    {
        public void EditProduct(int id, string name, decimal price)
        {
            var dataAccess = this.CreateDataAccess();
            var product = dataAccess.GetProductById(id);
            product.Name = name;
            product.Price = price;
            dataAccess.Save(product);
        }

        public virtual DataAccessLayer CreateDataAccess()
        {
            return new DataAccessLayer();
        }
    }
    public class DataAccessLayer 
    {
        public virtual Product GetProductById(int id)
        {
            // Expensive database call...
            // Omitted
            throw new NotImplementedException();
        }

        public virtual void Save(Product product)
        {
            // Omitted
            throw new NotImplementedException();
        }
    }

    public class Product
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public decimal Price { get; set; }
    }
}

In this example the CreateDataAccess method is the factory method pattern. Granted this is a very simple example, the method could contain a great deal of initialisation logic, or logic to determine which DataAccessLayer to return if there is more than one data store.  This could be useful when the database is partitioned (sharded) across multiple servers.

Things to note:

  • Always make factory methods virtual. This always for testing as well as other variations in other sub-classes.
  • Prefer to name the method with clear indicators about how it behaves.  I have chosen the word "Create" to inform consumers that each call to the method will create a new DataAccessLayer instance.
  • Prefer to make the return type an interface. This may not be feasible with legacy code, hence my demo here uses virtual methods. This is easier to introduce into an existing code base than an interface. Although if its possible introduce an interface.
Here's the test code to test the ProductMaintenance class.

namespace TestProject1
{
    using FactoryMethodDemo;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Rhino.Mocks;
public class ProductMaintenanceTestHarness : ProductMaintenance { private DataAccessLayer mock; public ProductMaintenanceTestHarness(DataAccessLayer mockDataAccessLayer) { this.mock = mockDataAccessLayer; } public override DataAccessLayer CreateDataAccess() { return this.mock; } }
    [TestClass]
    public class ProductMaintenanceTest
    {
        public TestContext TestContext { get; set; }

        [TestMethod]
        public void EditProductTest()
        {
            var productTestData = new Product
            {
                Id = 1,
                Name = "Bar",
                Price = 89.95M,
            };

            var mockDataAccessLayer = MockRepository.GenerateMock<DataAccessLayer>();  // Able to mock because methods are virtual
            mockDataAccessLayer.Expect(m => m.GetProductById(1)).Return(productTestData);
            mockDataAccessLayer.Expect(m => m.Save(productTestData));

            var subject = new ProductMaintenanceTestHarness(mockDataAccessLayer);
            subject.EditProduct(1, "Foo", 99.99M);

            mockDataAccessLayer.VerifyAllExpectations();
            Assert.AreEqual(99.99M, productTestData.Price);
        }
    }
}