protected virtual Node *GetNodeForReading(int timeout)
        {
            for (; ;)
            {
                int   blockIndex = _nodeHeader->ReadStart;
                Node *node       = this[blockIndex];
                if (blockIndex == _nodeHeader->WriteEnd)
                {
                    // No data is available, wait for it
                    if (DataExists.WaitOne(timeout))
                    {
                        continue;
                    }

                    // Timeout
                    return(null);
                }

                #pragma warning disable 0420 // ignore ref to volatile warning - Interlocked API
                if (Interlocked.CompareExchange(ref _nodeHeader->ReadStart, node->Next, blockIndex) == blockIndex)
                {
                    return(node);
                }
                #pragma warning restore 0420

                // Another thread has already acquired this node for reading, try again
                continue;
            }
        }
Example #2
0
        /// <summary>
        /// Attempts to reserve a node from the linked-list for reading with the specified timeout
        /// </summary>
        /// <param name="timeout">The number of milliseconds to wait if a node is not immediately available for reading.</param>
        /// <returns>An unsafe pointer to the node if successful, otherwise null</returns>
        protected virtual Node *GetNodeForReading(int timeout)
        {
            if (_node_readpointer == -1)
            {
                Interlocked.Exchange(ref _node_readpointer, _nodeHeader->WriteLastIndex); //first read, init _readstart
            }
            //need to wait?
            long lastcounter = 0;

            Interlocked.Exchange(ref lastcounter, _nodeHeader->WriteLastCounter);
            if (_node_readcounter == -1)
            {
                _node_readcounter = lastcounter;//first read, init counter
            }
            if (_node_readcounter > lastcounter)
            {                     // No data is available, wait for it
                if (timeout <= 0) // check value and set default 10 s
                {
                    timeout = 10000;
                }
                DataExists.Reset();
                var starttick = Stopwatch.GetTimestamp();
                if (!DataExists.WaitOne(timeout))
                {
                    return(null);
                }
                DiagInfo.waitticks = Stopwatch.GetTimestamp() - starttick;
            }
            int   blockIndex = _node_readpointer;
            Node *node       = this[blockIndex];

            node->ReserveNodeRead();
            //set data for next node
            if (Interlocked.CompareExchange(ref _node_readpointer, node->Next, blockIndex) == blockIndex)
            {
                return(node);
            }
            throw new Exception("Another thread has already acquired this node for reading!");
        }