예제 #1
0
        public static Task WriteAndFlushManyAsync(this IChannelHandlerContext context, ICollection <object> messages)
        {
            if (messages is null || 0u >= (uint)messages.Count)
            {
                return(TaskUtil.Completed);
            }

            var taskList = ThreadLocalList <Task> .NewInstance();

            foreach (object m in messages)
            {
                taskList.Add(context.WriteAsync(m));
            }
            context.Flush();

            var writeCloseCompletion = Task.WhenAll(taskList);

            writeCloseCompletion.ContinueWith(s_returnAfterWriteAction, taskList, TaskContinuationOptions.ExecuteSynchronously);
            return(writeCloseCompletion);
        }
예제 #2
0
        private void AcquireAllLocks()
        {
            bool lockTaken = false;

            for (ThreadLocalList <T> list = this.m_headList; list != null; list = list.m_nextList)
            {
                try
                {
                    Monitor.Enter(list, ref lockTaken);
                }
                finally
                {
                    if (lockTaken)
                    {
                        list.m_lockTaken = true;
                        lockTaken        = false;
                    }
                }
            }
        }
예제 #3
0
        private List <T> ToList()
        {
            Debug.Assert(Monitor.IsEntered(GlobalListsLock));

            List <T>        list        = new List <T>();
            ThreadLocalList currentList = _headList;

            while (currentList != null)
            {
                Node currentNode = currentList._head;
                while (currentNode != null)
                {
                    list.Add(currentNode._value);
                    currentNode = currentNode._next;
                }
                currentList = currentList._nextList;
            }

            return(list);
        }
예제 #4
0
        private bool Steal(out T result, bool take)
        {
            bool       loop;
            List <int> versionsList = new List <int>();

            do
            {
                versionsList.Clear();
                loop = false;


                ThreadLocalList currentList = _headList;
                while (currentList != null)
                {
                    versionsList.Add(currentList._version);
                    if (currentList._head != null && TrySteal(currentList, out result, take))
                    {
                        return(true);
                    }
                    currentList = currentList._nextList;
                }

                currentList = _headList;
                foreach (int version in versionsList)
                {
                    if (version != currentList._version)
                    {
                        loop = true;
                        if (currentList._head != null && TrySteal(currentList, out result, take))
                        {
                            return(true);
                        }
                    }
                    currentList = currentList._nextList;
                }
            } while (loop);


            result = default(T);
            return(false);
        }
예제 #5
0
        /// <summary>
        /// Local helper function to retrieve a thread local list by a thread object
        /// </summary>
        /// <param name="forceCreate">Create a new list if the thread does ot exist</param>
        /// <returns>The local list object</returns>
        private ThreadLocalList GetThreadList(bool forceCreate)
        {
            ThreadLocalList list = _locals.Value;

            if (list != null)
            {
                return(list);
            }
            else if (forceCreate)
            {
                // Acquire the lock to update the _tailList pointer
                lock (GlobalListsLock)
                {
                    if (_headList == null)
                    {
                        list      = new ThreadLocalList(Environment.CurrentManagedThreadId);
                        _headList = list;
                        _tailList = list;
                    }
                    else
                    {
                        list = GetUnownedList();
                        if (list == null)
                        {
                            list = new ThreadLocalList(Environment.CurrentManagedThreadId);
                            _tailList._nextList = list;
                            _tailList           = list;
                        }
                    }
                    _locals.Value = list;
                }
            }
            else
            {
                return(null);
            }
            Debug.Assert(list != null);
            return(list);
        }
예제 #6
0
        /// <summary>
        /// Local helper function to retrieve a thread local list by a thread object
        /// </summary>
        /// <param name="forceCreate">Create a new list if the thread does ot exist</param>
        /// <returns>The local list object</returns>
        private ThreadLocalList GetThreadList(bool forceCreate)
        {
            ThreadLocalList list = m_locals.Value;

            if (list != null)
            {
                return(list);
            }
            else if (forceCreate)
            {
                // Acquire the lock to update the m_tailList pointer
                lock (GlobalListsLock)
                {
                    if (m_headList == null)
                    {
                        list       = new ThreadLocalList(Thread.CurrentThread);
                        m_headList = list;
                        m_tailList = list;
                    }
                    else
                    {
                        list = GetUnownedList();
                        if (list == null)
                        {
                            list = new ThreadLocalList(Thread.CurrentThread);
                            m_tailList.m_nextList = list;
                            m_tailList            = list;
                        }
                    }
                    m_locals.Value = list;
                }
            }
            else
            {
                return(null);
            }
            Debug.Assert(list != null);
            return(list);
        }
예제 #7
0
        private void AddInternal(ThreadLocalList list, T item)
        {
            bool lockTaken = false;

            try {
                Interlocked.Exchange(ref list._currentOp, (int)ListOperation.Add);

                if (list.Count < 2 || _needSync)
                {
                    list._currentOp = (int)ListOperation.None;
                    Monitor.Enter(list, ref lockTaken);
                }
                list.Add(item, lockTaken);
            }
            finally {
                list._currentOp = (int)ListOperation.None;
                if (lockTaken)
                {
                    Monitor.Exit(list);
                }
            }
        }
예제 #8
0
        private void AcquireAllLocks()
        {
            Debug.Assert(Monitor.IsEntered(GlobalListsLock));

            bool            lockTaken   = false;
            ThreadLocalList currentList = _headList;

            while (currentList != null)
            {
                try {
                    Monitor.Enter(currentList, ref lockTaken);
                }
                finally {
                    if (lockTaken)
                    {
                        currentList._lockTaken = true;
                        lockTaken = false;
                    }
                }
                currentList = currentList._nextList;
            }
        }
예제 #9
0
        private void AddInternal(ThreadLocalList <T> list, T item)
        {
            bool lockTaken = false;

            try
            {
                Interlocked.Exchange(ref list.m_currentOp, 1);
                if ((list.Count < 2) || this.m_needSync)
                {
                    list.m_currentOp = 0;
                    Monitor.Enter(list, ref lockTaken);
                }
                list.Add(item, lockTaken);
            }
            finally
            {
                list.m_currentOp = 0;
                if (lockTaken)
                {
                    Monitor.Exit(list);
                }
            }
        }
예제 #10
0
        /// <summary>
        /// local helper method to acquire all local lists locks
        /// </summary>
        private void AcquireAllLocks()
        {
            bool            lockTaken   = false;
            ThreadLocalList currentList = m_headList;

            while (currentList != null)
            {
                // Try/Finally bllock to avoid thread aport between acquiring the lock and setting the taken flag
                try
                {
                    Monitor2.Enter(currentList, ref lockTaken);
                }
                finally
                {
                    if (lockTaken)
                    {
                        currentList.m_lockTaken = true;
                        lockTaken = false;
                    }
                }
                currentList = currentList.m_nextList;
            }
        }
예제 #11
0
        /// <summary>
        /// Local helper function to Take or Peek an item from the bag
        /// </summary>
        /// <param name="result">To receive the item retrieved from the bag</param>
        /// <param name="take">True means Take operation, false means Peek operation</param>
        /// <returns>True if succeeded, false otherwise</returns>
        private bool TryTakeOrPeek(out T result, bool take)
        {
            // Get the local list for that thread, return null if the thread doesn't exit
            //(this thread never add before)
            ThreadLocalList list = GetThreadList(false);

            if (list == null || list.Count == 0)
            {
                return(Steal(out result, take));
            }

            bool lockTaken = false;

            try
            {
                if (take) // Take operation
                {
#pragma warning disable 0420
                    Interlocked.Exchange(ref list._currentOp, (int)ListOperation.Take);
#pragma warning restore 0420
                    //Synchronization cases:
                    // if the list count is less than or equal two to avoid conflict with any stealing thread
                    // if _needSync is set, this means there is a thread that needs to freeze the bag
                    if (list.Count <= 2 || _needSync)
                    {
                        // reset it back to zero to avoid deadlock with stealing thread
                        list._currentOp = (int)ListOperation.None;
                        Monitor.Enter(list, ref lockTaken);

                        // Double check the count and steal if it became empty
                        if (list.Count == 0)
                        {
                            // Release the lock before stealing
                            if (lockTaken)
                            {
                                try { }
                                finally
                                {
                                    lockTaken = false; // reset lockTaken to avoid calling Monitor.Exit again in the finally block
                                    Monitor.Exit(list);
                                }
                            }
                            return(Steal(out result, true));
                        }
                    }
                    list.Remove(out result);
                }
                else
                {
                    if (!list.Peek(out result))
                    {
                        return(Steal(out result, false));
                    }
                }
            }
            finally
            {
                list._currentOp = (int)ListOperation.None;
                if (lockTaken)
                {
                    Monitor.Exit(list);
                }
            }
            return(true);
        }
예제 #12
0
        public void Add(T item)
        {
            ThreadLocalList <T> threadList = this.GetThreadList(true);

            this.AddInternal(threadList, item);
        }
예제 #13
0
        /// <summary>
        /// 添加一个数据到 <see cref="ConcurrentBag{T}"/>中。
        /// </summary>
        /// <param name="item"></param>
        public void Add(T item)
        {
            ThreadLocalList list = GetThreadList(true);

            AddInternal(list, item);
        }
예제 #14
0
        protected internal override ReadOnlySequence <byte> _GetSequence(int index, int count)
        {
            if (0u >= (uint)count)
            {
                return(ReadOnlySequence <byte> .Empty);
            }

            int i = ToComponentIndex0(index);

            if (i == ToComponentIndex0(index + count - 1))
            {
                ComponentEntry c = _components[i];
                return(c.Buffer.GetSequence(c.Idx(index), count));
            }
            var buffers = ThreadLocalList <ReadOnlyMemory <byte> > .NewInstance(_componentCount);

            try
            {
                while (count > 0)
                {
                    ComponentEntry c           = _components[i];
                    IByteBuffer    s           = c.Buffer;
                    int            localLength = Math.Min(count, c.EndOffset - index);
                    switch (s.IoBufferCount)
                    {
                    case 0:
                        ThrowHelper.ThrowNotSupportedException();
                        break;

                    case 1:
                        if (s.IsSingleIoBuffer)
                        {
                            buffers.Add(s.GetReadableMemory(c.Idx(index), localLength));
                        }
                        else
                        {
                            var sequence0 = s.GetSequence(c.Idx(index), localLength);
                            foreach (var memory in sequence0)
                            {
                                buffers.Add(memory);
                            }
                        }
                        break;

                    default:
                        var sequence = s.GetSequence(c.Idx(index), localLength);
                        foreach (var memory in sequence)
                        {
                            buffers.Add(memory);
                        }
                        break;
                    }

                    index += localLength;
                    count -= localLength;
                    i++;
                }

                return(ReadOnlyBufferSegment.Create(buffers));
            }
            finally
            {
                buffers.Return();
            }
        }