Exemplo n.º 1
0
        /// <summary>
        /// Converts the set items to another type with equivalent hash codes.
        /// NOTE: This method is not threadsafe and the set cannot be safely used after conversion.
        /// </summary>
        /// <param name="convert">the function used to convert the items</param>
        /// <returns>The set with converted item set</returns>
        public ConcurrentBigSet <TNewItem> ConvertUnsafe <TNewItem>(Func <TItem, TNewItem> convert)
        {
            Contract.Requires(convert != null);

            var newItemsBuffer = new BigBuffer <TNewItem>(m_items.EntriesPerBufferBitWidth);
            var itemsCount     = m_count;

            newItemsBuffer.Initialize(itemsCount, (startIndex, entryCount) =>
            {
                TNewItem[] buffer = new TNewItem[entryCount];
                var accessor      = m_accessors.Items;
                int itemsIndex    = startIndex;

                // entryIndex is index in specific buffer array whereas itemsIndex is an index into the big buffer
                // Ensure entryIndex does not go past the set of valid items by constraining it to be less
                // itemsCount - startIndex
                for (int entryIndex = 0; entryIndex < entryCount && itemsIndex < itemsCount; entryIndex++, itemsIndex++)
                {
                    buffer[entryIndex] = convert(accessor[itemsIndex]);
                }

                return(buffer);
            });

            return(new ConcurrentBigSet <TNewItem>(
                       concurrencyLevel: m_locks.Length,
                       backingItemsBuffer: newItemsBuffer,
                       backingNodesBuffer: m_nodes,
                       backingBuckets: m_buckets,
                       nodeLength: m_nodeLength)
            {
                m_count = itemsCount,
            });
        }
Exemplo n.º 2
0
        /// <summary>
        /// Creates and returns set by deserialization
        /// </summary>
        /// <param name="reader">general reader</param>
        /// <param name="itemReader">item reader</param>
        /// <param name="concurrencyLevel">the concurrency level (all values less than 1024 will be assumed to be 1024)</param>
        public static ConcurrentBigSet <TItem> Deserialize(
            BinaryReader reader,
            Func <TItem> itemReader,
            int concurrencyLevel = DefaultConcurrencyLevel)
        {
            var count                  = reader.ReadInt32();
            var nodeLength             = reader.ReadInt32();
            var itemsPerBufferBitWidth = reader.ReadInt32();
            var capacity               = Math.Max(MinConcurrencyLevel, Math.Max(nodeLength, concurrencyLevel));

            var items = new BigBuffer <TItem>(itemsPerBufferBitWidth);

            items.Initialize(capacity);
            var nodes = new BigBuffer <Node>(NodesPerEntryBufferBitWidth);

            nodes.Initialize(capacity);

            var itemsAccessor = items.GetAccessor();
            var nodesAccessor = nodes.GetAccessor();

            List <int> freeNodes = new List <int>();

            for (int i = 0; i < nodeLength; i++)
            {
                var hashCode = reader.ReadInt32();
                if (hashCode != Node.UnusedHashCode)
                {
                    var next = reader.ReadInt32();
                    var item = itemReader();
                    nodesAccessor[i] = new Node(hashCode, next);
                    itemsAccessor[i] = item;
                }
                else
                {
                    freeNodes.Add(i);
                }
            }

            var buckets = Buckets.Deserialize(reader);
            var result  = new ConcurrentBigSet <TItem>(
                concurrencyLevel,
                items,
                nodes,
                buckets,
                nodeLength);

            result.m_count = count;

            // distribute free nodes
            var accessors = result.m_accessors;

            foreach (var i in freeNodes)
            {
                var lockNo = result.GetLockNo(i);
                result.AddFreeNode(lockNo, i, ref accessors);
            }

            return(result);
        }
Exemplo n.º 3
0
            /// <summary>
            /// Class constructor
            /// </summary>
            public Buckets(int capacity, int ratio, BigBuffer <int> .BufferInitializer bucketsBufferInitializer = null, bool initializeSequentially = false)
            {
                Contract.Requires(capacity > 0);
                var buckets = new BigBuffer <int>(ItemsPerEntryBufferBitWidth, 1);

                capacity  = buckets.Initialize(capacity, bucketsBufferInitializer ?? InitializeBucketBufferToInvalidHeadNodeIndices, initializeSequentially);
                m_buckets = buckets;
                Contract.Assume(((capacity - 1) & capacity) == 0, "capacity must be a power of two");
                m_lastBucketIndex       = capacity - 1;
                m_preSplitBucketsLength = capacity;
                SplitThreshold          = checked (capacity * ratio);
                m_splitBucketCursor     = int.MinValue;
            }
Exemplo n.º 4
0
            private Buckets(BigBuffer <int> .BufferInitializer bucketsBufferInitializer, int capacity, int lastBucketIndex, int pendingSplitBucketCount, int preSplitBucketsLength, int isSplitting, int splitThreshold, int splitBucketCursor)
            {
                Contract.Requires(bucketsBufferInitializer != null);

                var buckets = new BigBuffer <int>(ItemsPerEntryBufferBitWidth, 1);

                buckets.Initialize(capacity, bucketsBufferInitializer, initializeSequentially: true);
                m_buckets                 = buckets;
                m_lastBucketIndex         = lastBucketIndex;
                m_preSplitBucketsLength   = preSplitBucketsLength;
                m_pendingSplitBucketCount = pendingSplitBucketCount;
                IsSplitting               = isSplitting;
                SplitThreshold            = splitThreshold;
                m_splitBucketCursor       = splitBucketCursor;
            }
Exemplo n.º 5
0
            /// <summary>
            /// Attempts to get the next bucket that requires splitting if splitting is active
            /// </summary>
            public bool TryGetBucketToSplit(out int bucketToSplitNo, out int targetBucketNo)
            {
                targetBucketNo  = -1;
                bucketToSplitNo = -1;

                if (Volatile.Read(ref IsSplitting) == SPLITTING_TRUE)
                {
                    bucketToSplitNo = Interlocked.Increment(ref m_splitBucketCursor);
                    bool isValidBucketToSplit = unchecked ((uint)bucketToSplitNo < (uint)m_preSplitBucketsLength);
                    if (isValidBucketToSplit)
                    {
                        targetBucketNo = bucketToSplitNo + m_preSplitBucketsLength;
                        m_buckets.Initialize(targetBucketNo + 1, m_bucketsBufferInitializer);
                        return(true);
                    }
                }

                return(false);
            }