Click here to Skip to main content
12,630,410 members (28,780 online)
Click here to Skip to main content

Stats

64.5K views
3.1K downloads
72 bookmarked
Posted

A Concurrent Collection: a MultiMap Generic Collection Class in C# - Part 2

, 5 Jun 2009 CPOL
MultiMap is similar to a .NET Dictionary collection type, but accepts duplicate Key,Value pairs during addition. The MultiMap collection is also a concurrent collection.
ConsoleTest
bin
Release
ConsoleTest.exe
MultiMap.dll
Properties
MultiMap
bin
Release
MultiMap.dll
MultiMap.suo
Properties
MultiMapTest
bin
Release
MultiMap.dll
MultiMapTest.exe
Properties
Demo
MultiMap.dll
MultiMapTest.exe
MultiMap.dll
Debug
MultiMap.dll
MultiMap.pdb
MultiMapTest.exe
MultiMapTest.pdb
MultiMapTest.vshost.exe
MultiMap.dll
MultiMap.pdb
MultiMapTest.exe
MultiMapTest.pdb
MultiMapTest.vshost.exe
MultiMapTest.vshost.exe.manifest
obj
Debug
MultiMapTest.csproj.GenerateResource.Cache
MultiMapTest.exe
MultiMapTest.Form1.resources
MultiMapTest.pdb
MultiMapTest.Properties.Resources.resources
TempPE
Release
MultiMapTest.csproj.GenerateResource.Cache
MultiMapTest.exe
MultiMapTest.Form1.resources
MultiMapTest.pdb
MultiMapTest.Properties.Resources.resources
TempPE
Debug
ConsoleTest.exe
ConsoleTest.pdb
ConsoleTest.vshost.exe
MultiMap.dll
MultiMap.pdb
ConsoleTest.exe
ConsoleTest.pdb
ConsoleTest.vshost.exe
ConsoleTest.vshost.exe.manifest
MultiMap.dll
MultiMap.pdb
obj
Debug
ConsoleTest.exe
ConsoleTest.pdb
TempPE
Release
ConsoleTest.exe
ConsoleTest.pdb
ResolveAssemblyReference.cache
TempPE
Debug
MultiMap.dll
MultiMap.pdb
MultiMap.dll
MultiMap.pdb
obj
Debug
MultiMap.dll
MultiMap.pdb
TempPE
Release
MultiMap.dll
MultiMap.pdb
TempPE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace BK.Util
{
    internal class LockDetails<Key, Value> where Key:IComparable<Key>
    {
        private int numberOfThreadsLockedThisKey;
        private Dictionary<string, ThreadDetails<Key, Value>> listOfThreadsLockingItems;
        private List<Value> listOfValuesMarkedForDeletion;
        private AutoResetEvent eventToWaitOnDeletion;
        private bool itemMarkedForDeleteAll;
        private bool itemMarkedForDelete;
        private MultimapBK<Key,Value> mainInstance;
        private object lockThis = new object();
        private int NotifyOnDeletion;

        internal bool IsItemVisibleToThisThread(string ThreadId)
        {
            bool retValue = false;
            ThreadDetails<Key,Value> result = null;
            if (listOfThreadsLockingItems.TryGetValue(ThreadId, out result))
            {
                retValue = true;
            }

            return retValue;
        }

        internal LockDetails(MultimapBK<Key, Value> MultiMapInstance)
        {
            mainInstance = MultiMapInstance;
            listOfValuesMarkedForDeletion = new List<Value>();
            listOfThreadsLockingItems = new Dictionary<string, ThreadDetails<Key, Value>>();
            eventToWaitOnDeletion = new AutoResetEvent(false);
            NotifyOnDeletion = 0;
        }

        internal void Initialize(MultimapBK<Key,Value> MultiMapInstance, Key KeyInAccess, ThreadDetails<Key,Value> ThreadRequesting)
        {
            lock (lockThis)
            {
                itemMarkedForDeleteAll = false;
                ThreadDetails<Key, Value> threadDetails = null;
                if (!listOfThreadsLockingItems.TryGetValue(ThreadRequesting.ThreadId, out threadDetails))
                {
                    numberOfThreadsLockedThisKey++;
                }
                // else this item is already locked by this Thread.  So no need to increment the count.
            }
        }
        internal void RemoveLock(Key KeyInAccess, ThreadDetails<Key, Value> ThreadRequesting)
        {
            ThreadDetails<Key, Value> threadDetails = null;
            if (listOfThreadsLockingItems.TryGetValue(ThreadRequesting.ThreadId, out threadDetails))
            {
                lock (lockThis)
                {
                    numberOfThreadsLockedThisKey--;
                    listOfThreadsLockingItems.Remove(ThreadRequesting.ThreadId);
                    if (numberOfThreadsLockedThisKey <= 0 && itemMarkedForDeleteAll)
                    {
                        mainInstance.DeleteAll(KeyInAccess);
                    }
                    else if (numberOfThreadsLockedThisKey <= 0 && itemMarkedForDelete)
                    {
                        int Counter = 0;
                        while (Counter < listOfValuesMarkedForDeletion.Count)
                        {
                            mainInstance.Delete(KeyInAccess, listOfValuesMarkedForDeletion[Counter]);
                            Counter++;
                        }

                        listOfValuesMarkedForDeletion.Clear();
                        itemMarkedForDelete = false;

                        while (NotifyOnDeletion != 0)
                        {
                            eventToWaitOnDeletion.Set();
                            NotifyOnDeletion--;
                        }
                    }
                }
            }
        }

        internal void AddLock(Key KeyInAccess, ThreadDetails<Key, Value> ThreadRequesting)
        {
            ThreadDetails<Key, Value> threadDetails = null;
            if (!listOfThreadsLockingItems.TryGetValue(ThreadRequesting.ThreadId, out threadDetails))
            {
                numberOfThreadsLockedThisKey++;
                listOfThreadsLockingItems.Add(ThreadRequesting.ThreadId, ThreadRequesting);
            }
        }

        internal bool ItemMarkedForDeleteAll
        {
            get
            {

                return itemMarkedForDeleteAll;
            }
        }

        internal bool ItemMarkedForDelete
        {
            get
            {
                return itemMarkedForDelete;
            }
        }

        internal void AddValueToBeDeleted(Key KeyItem, Value ValueToBeDeleted)
        {
            lock (lockThis)
            {
                if (numberOfThreadsLockedThisKey <= 0)
                {
                    mainInstance.Delete(KeyItem, ValueToBeDeleted);
                }
                else
                {
                    itemMarkedForDelete = true;
                    listOfValuesMarkedForDeletion.Add(ValueToBeDeleted);
                }
            }
        }

        internal void AddKeyToBeDeleted(Key KeyItem)
        {
            lock (lockThis)
            {
                if (numberOfThreadsLockedThisKey <= 0)
                {
                    mainInstance.DeleteAll(KeyItem);
                }
                else
                {
                    itemMarkedForDeleteAll = true;
                }
            }
        }

        internal AutoResetEvent NotifyOnDeletionComplete()
        {
            NotifyOnDeletion++;

            return eventToWaitOnDeletion;
        }




    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Bharath K A
Software Developer (Senior)
United States United States
No Biography provided

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.161205.3 | Last Updated 5 Jun 2009
Article Copyright 2009 by Bharath K A
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid