/// <summary>
        /// Returns a snapshot of the elements.
        /// </summary>
        /// <returns></returns>
        internal static T[] ToArray <T>(UnsafeMPSCQueue *queue) where T : unmanaged
        {
            UDebug.Assert(queue != null);
            UDebug.Assert(queue->_items.Ptr != null);
            UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle);

            int count = GetCount(queue);
            var arr   = new T[count];

            var enumerator = GetEnumerator <T>(queue);

            int i = 0;

            while (enumerator.MoveNext() && i < count)
            {
                arr[i++] = enumerator.Current;
            }


            return(arr);
        }
Beispiel #2
0
        public void ResetAll(params string[] excludeKeys)
        {
            UDebug.Log($"SaveService Reset All exlude => {excludeKeys.AsString()}".Colored(ConsoleTextColor.yellow));
            foreach (var pair in registeredSaveables)
            {
                if (pair.Value != null)
                {
                    string excludedKey = Array.Find(excludeKeys, key => key == pair.Value.SaveKey);

                    if (string.IsNullOrEmpty(excludedKey))
                    {
                        pair.Value.ResetFull();
                    }
                    else
                    {
                        UDebug.Log($"Key => {pair.Value.SaveKey} was excluded from resetting".Colored(ConsoleTextColor.yellow));
                    }
                }
            }
            SaveAll();
        }
Beispiel #3
0
        /// <summary>
        /// Enqueues an item in the queue. Blocks the thread until there is space in the queue.
        /// </summary>
        public static void Enqueue <T>(UnsafeSPSCQueue *queue, T item) where T : unmanaged
        {
            UDebug.Assert(queue != null);
            UDebug.Assert(queue->_items.Ptr != null);
            UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle);

            SpinWait spinner  = default;
            var      tail     = Volatile.Read(ref queue->_headAndTail.Tail);
            var      nextTail = GetNext(tail, queue->_items.Length);


            // Full Queue
            while (nextTail == Volatile.Read(ref queue->_headAndTail.Head))
            {
                spinner.SpinOnce();
            }

            *queue->_items.Element <T>(tail) = item;

            Volatile.Write(ref queue->_headAndTail.Tail, nextTail);
        }
        /// <summary>
        /// Tries to enqueue an item in the queue. Returns false if there's no space in the queue.
        /// </summary>
        public static bool TryEnqueue <T>(UnsafeMPSCQueue *queue, T item) where T : unmanaged
        {
            UDebug.Assert(queue != null);
            UDebug.Assert(queue->_items.Ptr != null);
            UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle);

            SpinWait spinner = default;

            // Temp copy of inner buffer
            var items  = queue->_items;
            var offset = queue->_slotOffset;

            while (true)
            {
                int tail  = Volatile.Read(ref queue->_headAndTail.Tail);
                int index = tail & queue->_mask;

                int seq = Volatile.Read(ref *(int *)items.Element(index, offset));
                int dif = seq - tail;

                if (dif == 0)
                {
                    // Reserve the slot
                    if (Interlocked.CompareExchange(ref queue->_headAndTail.Tail, tail + 1, tail) == tail)
                    {
                        // Write the value and update the seq
                        *items.Element <T>(index) = item;
                        Volatile.Write(ref *(int *)items.Element(index, offset), tail + 1);
                        return(true);
                    }
                }
                else if (dif < 0)
                {
                    // Slot was full
                    return(false);
                }
                // Lost the race, try again
                spinner.SpinOnce();
            }
        }
Beispiel #5
0
        /// <summary>
        /// Tries to dequeue an item from the queue. Returns false if there's no items in the queue.
        /// </summary>
        public static bool TryDequeue <T>(UnsafeSPSCQueue *queue, out T result) where T : unmanaged
        {
            UDebug.Assert(queue != null);
            UDebug.Assert(queue->_items.Ptr != null);
            UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle);

            var head = Volatile.Read(ref queue->_headAndTail.Head);

            // Queue empty
            if (Volatile.Read(ref queue->_headAndTail.Tail) == head)
            {
                result = default;
                return(false);
            }

            result = *queue->_items.Element <T>(head);
            var nextHead = GetNext(head, queue->_items.Length);

            Volatile.Write(ref queue->_headAndTail.Head, nextHead);

            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// Dequeues an item from the queue. Blocks the thread until there is space in the queue.
        /// </summary>
        public static T Dequeue <T>(UnsafeSPSCQueue *queue) where T : unmanaged
        {
            UDebug.Assert(queue != null);
            UDebug.Assert(queue->_items.Ptr != null);
            UDebug.Assert(typeof(T).TypeHandle.Value == queue->_typeHandle);

            SpinWait spinner = default;
            var      head    = Volatile.Read(ref queue->_headAndTail.Head);

            // Queue empty
            while (Volatile.Read(ref queue->_headAndTail.Tail) == head)
            {
                spinner.SpinOnce();
            }

            var result   = queue->_items.Element <T>(head);
            var nextHead = GetNext(head, queue->_items.Length);

            Volatile.Write(ref queue->_headAndTail.Head, nextHead);

            return(*result);
        }
        static Entry *CreateEntry <T>(UnsafeOrderedCollection *collection, T key, out int entryIndex) where T : unmanaged
        {
            Entry *entry;

            if (collection->FreeHead > 0)
            {
                UDebug.Assert(collection->FreeCount > 0);

                // grab from free head
                entry = GetEntry(collection, entryIndex = collection->FreeHead);

                // new free-head is entrys left pointer
                collection->FreeHead  = entry->Left;
                collection->FreeCount = collection->FreeCount - 1;

                // we have to clear left pointer
                entry->Left = 0;
            }
            else
            {
                // this has to hold, as Insert<T> checks and expands if needed
                UDebug.Assert(collection->UsedCount < collection->Entries.Length);

                // grab entry from UsedCount, we add increment before as entries are 1 indexed
                entry = GetEntry(collection, entryIndex = ++collection->UsedCount);
            }

            // when we get a new entry, it's left/right/balance all have to be zero
            UDebug.Assert(entry->Left == 0);
            UDebug.Assert(entry->Right == 0);
            UDebug.Assert(entry->Balance == 0);

            // write key to entry
            *(T *)((byte *)entry + collection->KeyOffset) = key;

            // return entry
            return(entry);
        }