public void Enqueue(IoTask task)
            {
                if (_disposed)
                {
                    throw new ObjectDisposedException(GetType().FullName);
                }

                IoTask last = _last, newLast;

                while (last != null && !ReferenceEquals(last, newLast = Interlocked.CompareExchange(ref _last, task, last)))
                {
                    last = newLast;
                }

                if (last == null)
                {
                    throw new IOException();
                }

                IoTask prev = Interlocked.Exchange(ref last.Next, task);

                if (prev != null)
                {
                    throw new IOException();
                }

                _wakeup.Set();
            }
            public WorkerState(Stream output, bool closeStream)
            {
                _output      = output;
                _closeStream = closeStream;
                _first       = _last = new IoTask();
                _wakeup      = new ManualResetEvent(false);
                _stop        = new ManualResetEvent(false);

                _worker = new Thread(WriterThread);
                _worker.IsBackground = true;
                _worker.SetApartmentState(ApartmentState.MTA);
                _worker.Name = GetType().Name;
                _worker.Start();
            }
        /// <summary>
        /// Returns a number of bytes up to length that is pending a write at the position specified and
        /// copies those bytes into buffer the offset provided.
        /// </summary>
        public int Read(long position, byte[] buffer, int offset, int length)
        {
            IoTask work       = _state.First();
            int    bytesFound = 0;

            while (work != null)
            {
                if (work.Position == position)
                {
                    Buffer.BlockCopy(work.Bytes, work.Offset, buffer, offset, bytesFound = Math.Min(length, work.Length));
                }
                work = work.Next;
            }

            return(bytesFound);
        }
            void WriterThread()
            {
                try
                {
                    byte[]       buffer = new byte[8192];
                    WaitHandle[] waits  = new WaitHandle[] { _stop, _wakeup };
                    while (true)
                    {
                        int result = WaitHandle.WaitAny(waits);
                        _wakeup.Reset();
                        while (PerformWrite(ref buffer))
                        {
                        }

                        if (result != 1)
                        {
                            break;
                        }
                    }

                    _output.Flush();
                    // Console.WriteLine("Thread {0} write lag = {1}", Thread.CurrentThread.ManagedThreadId, _lagging);
                    Debug.Write(
                        String.Format("Thread {0} write lag = {1}", Thread.CurrentThread.ManagedThreadId, _lagging),
                        GetType().Name
                        );
                }
                catch (ThreadAbortException) { throw; }
                catch
                {
                    _first = null;
                    Interlocked.Exchange(ref _last, null);
                }
                finally
                {
                    if (_closeStream)
                    {
                        _output.Close();
                    }
                }
            }
Пример #5
0
            public void Enqueue(IoTask task)
            {
                if (_disposed)
                    throw new ObjectDisposedException(GetType().FullName);

                IoTask last = _last, newLast;
                while (last != null && !ReferenceEquals(last, newLast = Interlocked.CompareExchange(ref _last, task, last)))
                    last = newLast;

                if (last == null)
                    throw new IOException();

                IoTask prev = Interlocked.Exchange(ref last.Next, task);
                if (prev != null)
                    throw new IOException();

                _wakeup.Set();
            }
Пример #6
0
            private bool PerformWrite(ref byte[] buffer)
            {
                IoTask start = _first;
                IoTask next = Interlocked.CompareExchange(ref start.Next, null, null);
                if (next == null)
                    return false;//nothing to do, _first has always been processed

                IoTask stop = start = next;

                bool hasSignals = start.Signal != null;
                int byteLen = stop.Length;
                long startpos = stop.Position;
                long position = stop.Position + byteLen;

                while (null != (next = Interlocked.CompareExchange(ref start.Next, null, null)))
                {
                    //see if both are append-only (position < 0)
                    if (startpos < 0 && next.Position >= 0)
                        break;
                    //see if the next write immediately follows this
                    if (startpos >= 0 && next.Position != position)
                        break;
                    //see if this write will overflow our max memory buffer limit
                    if (next.Length + byteLen > MemoryLimit)
                        break;
                    if (next.IoAction != null)
                        break;

                    byteLen += next.Length;
                    position += next.Length;
                    hasSignals |= next.Signal != null;
                    stop = next;
                }

                if (start.IoAction != null)
                {
                    start.IoAction(_output);
                    start.IoAction = null;
                }
                else if (ReferenceEquals(start, stop))
                {
                    if (startpos >= 0)
                        _output.Position = startpos;

                    _output.Write(start.Bytes, start.Offset, start.Length);
                }
                else //buffer and write multiple items...
                {
                    if (buffer.Length < byteLen)
                        Array.Resize(ref buffer, byteLen + 8192);

                    int counter = 0;
                    int offset = 0;
                    IoTask current = start;
                    while (true)
                    {
                        counter++;
                        Buffer.BlockCopy(current.Bytes, current.Offset, buffer, offset, current.Length);
                        offset += current.Length;

                        if (ReferenceEquals(current, stop))
                            break;
                        current = current.Next;
                    }

                    _lagging = Math.Max(_lagging, counter);

                    if (startpos >= 0)
                        _output.Position = startpos;

                    _output.Write(buffer, 0, offset);
                }

                while (hasSignals)
                {
                    if (start.Signal != null)
                    {
                        start.Signal.Set();
                        start.Signal = null;
                    }
                    if (ReferenceEquals(start, stop))
                        break;
                    start = start.Next;
                }

                _first = stop;
                return true;
            }
Пример #7
0
            void WriterThread()
            {
                try
                {
                    byte[] buffer = new byte[8192];
                    WaitHandle[] waits = new WaitHandle[] { _stop, _wakeup };
                    while (true)
                    {
                        int result = WaitHandle.WaitAny(waits);
                        _wakeup.Reset();
                        while (PerformWrite(ref buffer))
                        { }

                        if (result != 1)
                            break;
                    }

                    _output.Flush();
                    // Console.WriteLine("Thread {0} write lag = {1}", Thread.CurrentThread.ManagedThreadId, _lagging);
                    Debug.Write(
                        String.Format("Thread {0} write lag = {1}", Thread.CurrentThread.ManagedThreadId, _lagging),
                        GetType().Name
                        );
                }
                catch (ThreadAbortException) { throw; }
                catch
                {
                    _first = null;
                    Interlocked.Exchange(ref _last, null);
                }
                finally
                {
                    if (_closeStream)
                        _output.Close();
                }
            }
Пример #8
0
            public WorkerState(Stream output, bool closeStream)
            {
                _output = output;
                _closeStream = closeStream;
                _first = _last = new IoTask();
                _wakeup = new ManualResetEvent(false);
                _stop = new ManualResetEvent(false);

                _worker = new Thread(WriterThread);
                _worker.IsBackground = true;
                _worker.SetApartmentState(ApartmentState.MTA);
                _worker.Name = GetType().Name;
                _worker.Start();
            }
            private bool PerformWrite(ref byte[] buffer)
            {
                IoTask start = _first;
                IoTask next  = Interlocked.CompareExchange(ref start.Next, null, null);

                if (next == null)
                {
                    return(false);//nothing to do, _first has always been processed
                }
                IoTask stop = start = next;

                bool hasSignals = start.Signal != null;
                int  byteLen    = stop.Length;
                long startpos   = stop.Position;
                long position   = stop.Position + byteLen;

                while (null != (next = Interlocked.CompareExchange(ref start.Next, null, null)))
                {
                    //see if both are append-only (position < 0)
                    if (startpos < 0 && next.Position >= 0)
                    {
                        break;
                    }
                    //see if the next write immediately follows this
                    if (startpos >= 0 && next.Position != position)
                    {
                        break;
                    }
                    //see if this write will overflow our max memory buffer limit
                    if (next.Length + byteLen > MemoryLimit)
                    {
                        break;
                    }
                    if (next.IoAction != null)
                    {
                        break;
                    }

                    byteLen    += next.Length;
                    position   += next.Length;
                    hasSignals |= next.Signal != null;
                    stop        = next;
                }

                if (start.IoAction != null)
                {
                    start.IoAction(_output);
                    start.IoAction = null;
                }
                else if (ReferenceEquals(start, stop))
                {
                    if (startpos >= 0)
                    {
                        _output.Position = startpos;
                    }

                    _output.Write(start.Bytes, start.Offset, start.Length);
                }
                else //buffer and write multiple items...
                {
                    if (buffer.Length < byteLen)
                    {
                        Array.Resize(ref buffer, byteLen + 8192);
                    }

                    int    counter = 0;
                    int    offset  = 0;
                    IoTask current = start;
                    while (true)
                    {
                        counter++;
                        Buffer.BlockCopy(current.Bytes, current.Offset, buffer, offset, current.Length);
                        offset += current.Length;

                        if (ReferenceEquals(current, stop))
                        {
                            break;
                        }
                        current = current.Next;
                    }

                    _lagging = Math.Max(_lagging, counter);

                    if (startpos >= 0)
                    {
                        _output.Position = startpos;
                    }

                    _output.Write(buffer, 0, offset);
                }

                while (hasSignals)
                {
                    if (start.Signal != null)
                    {
                        start.Signal.Set();
                        start.Signal = null;
                    }
                    if (ReferenceEquals(start, stop))
                    {
                        break;
                    }
                    start = start.Next;
                }

                _first = stop;
                return(true);
            }