{"id":501,"date":"2021-07-23T08:39:58","date_gmt":"2021-07-23T08:39:58","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=501"},"modified":"2021-07-24T00:40:45","modified_gmt":"2021-07-24T00:40:45","slug":"cchashset-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2021\/07\/23\/cchashset-cs\/","title":{"rendered":"CcHashSet.cs"},"content":{"rendered":"\n<p>Concurrent HashSet Class without Blocking<\/p>\n\n\n\n<p>Updated: July-23,2021<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Threading;\n[DebuggerDisplay(\"Count = {\" + nameof(Count) + \"}\")]\npublic class CcHashSet&lt;T> : IEnumerable\n{\n    private readonly HashSet&lt;T>[]         _array;\n    private readonly int                  _size;\n    private volatile int[]                _activeThreads;\n    private volatile int                  _bP;\n    private readonly IEqualityComparer&lt;T> _comparer;\n    public volatile  int                  NumberOfActiveThreads;\n    public CcHashSet() : this(1024, null)\n    {\n    }\n    public CcHashSet(int size) : this(size, null)\n    {\n    }\n    public CcHashSet(int size, IEqualityComparer&lt;T> comparer)\n    {\n        if (comparer == null)\n            _comparer = EqualityComparer&lt;T>.Default;\n        else\n            _comparer = comparer;\n        ThreadPool.GetMaxThreads(out var nW, out var nI);\n        _array                = new HashSet&lt;T>[nW];\n        _size                 = size;\n        NumberOfActiveThreads = 0;\n        _bP                   = 0;\n        _activeThreads        = new int[Environment.ProcessorCount];\n        _activeThreads.Fill(-1);\n    }\n    public int Count\n    {\n        get\n        {\n            var totalCount = 0;\n            for (var i = 0; i &lt; _activeThreads.Length; ++i)\n                if (_activeThreads[i] != -1)\n                    if (_array[_activeThreads[i]] != null)\n                        totalCount += _array[_activeThreads[i]].Count;\n            return totalCount;\n        }\n    }\n    IEnumerator IEnumerable.GetEnumerator()\n    {\n        return GetEnum();\n    }\n    public IEnumerator&lt;T> GetEnumerator()\n    {\n        return GetEnum();\n    }\n    public void Add(T item)\n    {\n        var id = Thread.CurrentThread.ManagedThreadId;\n        if (_array[id] == null)\n        {\n            _array[id] = new HashSet&lt;T>(_size, _comparer);\n            Interlocked.Increment(ref NumberOfActiveThreads);\n            if (_bP >= _activeThreads.Length)\n            {\n                var nAtA = new int[_activeThreads.Length &lt;&lt; 1];\n                nAtA.Fill(-1);\n                for (var i = 0; i &lt; _activeThreads.Length; ++i)\n                    if (_activeThreads[i] != -1)\n                        nAtA[i] = _activeThreads[i];\n                _activeThreads = nAtA;\n            }\n            _activeThreads[_bP] = id;\n            Interlocked.Increment(ref _bP);\n        }\n        if (!Contains(item))\n            _array[id].Add(item);\n    }\n    public bool Contains(T item)\n    {\n        for (var i = 0; i &lt; _activeThreads.Length; ++i)\n            if (_activeThreads[i] != -1)\n                if (_array[_activeThreads[i]] != null)\n                    if (_array[_activeThreads[i]].Contains(item))\n                        return true;\n        return false;\n    }\n    public IEnumerator&lt;T> GetEnum()\n    {\n        var arr = ToArray();\n        foreach (var i in arr)\n            yield return i;\n    }\n    public T[] ToArray()\n    {\n        var totalCount = 0;\n        for (var i = 0; i &lt; _activeThreads.Length; ++i)\n            if (_activeThreads[i] != -1)\n                if (_array[_activeThreads[i]] != null)\n                    totalCount += _array[_activeThreads[i]].Count;\n        var ta  = new T[totalCount];\n        var ptr = 0;\n        for (var i = 0; i &lt; _activeThreads.Length; ++i)\n            if (_activeThreads[i] != -1)\n                if (_array[_activeThreads[i]] != null)\n                {\n                    var it = _array[_activeThreads[i]].ToArray();\n                    for (var j = 0; j &lt; it.Length; ++j)\n                        ta[ptr++] = it[j];\n                }\n        return ta;\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Concurrent HashSet Class without Blocking Updated: July-23,2021<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[84,58,207],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/501"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=501"}],"version-history":[{"count":2,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/501\/revisions"}],"predecessor-version":[{"id":503,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/501\/revisions\/503"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}