Exemplo n.º 1
0
        FilePacketMemoryStream Dequeue()
        {
            var buf = new byte[packetQueue[nextBufIndexToConsume].FilledLength];

            System.Buffer.BlockCopy(packetQueue[nextBufIndexToConsume].Buffer, 0, buf, 0, buf.Length);
            var result = new FilePacketMemoryStream
            {
                Index        = packetQueue[nextBufIndexToConsume].Index,
                MemoryStream = new MemoryStream(buf)
            };

            nextBufIndexToConsume++;
            if (nextBufIndexToConsume == queueDepth)
            {
                nextBufIndexToConsume = 0;
            }
            queueFilledCount--;
            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get the next piece of the compressed file
        /// </summary>
        /// <returns>Packet containing part of the compressed file, or null, if file is ended</returns>
        /// <param name="cancel">Cancellation flag</param>
        public FilePacketMemoryStream Consume(out bool cancel)
        {
            FilePacketMemoryStream result = null;

            var taken = true;

            mutex.WaitOne();
            try
            {
                cancel = cancelled;
                if (cancel)
                {
                    return(result); // Пустой результат.
                }
                var eventType = EventsForConsumer.PacketsExists;
                // If queue is empty, begin to await when it's filled
                while (queue.CountContiguous == 0 && activeCompressorThreads != 0)
                {
                    taken = false;
                    mutex.ReleaseMutex();

                    eventType = (EventsForConsumer)WaitHandle.WaitAny(eventsForConsumer);
                    mutex.WaitOne();
                    taken = true;

                    if ((eventType == EventsForConsumer.PacketAppeared && queue.CountContiguous != 0) ||
                        eventType == EventsForConsumer.ProductionCompleted ||
                        eventType == EventsForConsumer.Cancel)
                    {
                        break;
                    }
                }

                // If queue is empty and all compressor threads finished their work, we are finishing our work too
                if (queue.CountContiguous == 0 && activeCompressorThreads == 0)
                {
                    return(result); // Empty result
                }
                switch (eventType)
                {
                case EventsForConsumer.PacketsExists:
                case EventsForConsumer.PacketAppeared:
                    var hasSpace = queue.HaveSpace();
                    result = queue.Dequeue();
                    if (!hasSpace && queue.HaveSpace())     // If one new free space appeared in the queue, send signal to the producer
                    {
                        eventForNewSpaceInQueue.Set();
                    }
                    if (eventType == EventsForConsumer.PacketAppeared && queue.CountContiguous == 0)
                    {
                        eventForFirstPacketInQueue.Reset();     // Resetting our signal about packet appearing
                    }
                    break;

                case EventsForConsumer.ProductionCompleted:
                    // Do nothing, just returning the pre-initialized empty result below
                    break;

                case EventsForConsumer.Cancel:
                    cancel = true;
                    break;

                default:
                    Debug.Write($"Unsupported event type for consumer: {Enum.GetName(typeof(EventsForConsumer), eventType)}");
                    break;
                }
            }
            finally
            {
                if (taken)
                {
                    mutex.ReleaseMutex();
                }
            }

            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Putting compressed &quot;packet&quot; into the queue
        /// </summary>
        /// <param name="filePacket">Piece of compressed file</param>
        /// <param name="cancel">Cancellation flag</param>
        public void Produce(FilePacketMemoryStream filePacket, out bool cancel)
        {
            Debug.Assert(filePacket != null, $"{nameof(filePacket)} is null");

            var taken = true;

            mutex.WaitOne();
            try
            {
                cancel = cancelled;
                if (cancelled)
                {
                    return;
                }

                var eventType = EventsForProducer.SpaceExists;
                // If queue is full, begin to await for freeing space
                while (!queue.CanEnqueue(filePacket))
                {
                    taken = false;
                    mutex.ReleaseMutex();

                    eventType = (EventsForProducer)WaitHandle.WaitAny(eventsForProducer);
                    mutex.WaitOne();
                    taken = true;

                    if ((eventType == EventsForProducer.SpaceAppeared && queue.CanEnqueue(filePacket)) ||
                        eventType == EventsForProducer.Cancel)
                    {
                        break;
                    }
                }
                switch (eventType)
                {
                case EventsForProducer.SpaceExists:
                case EventsForProducer.SpaceAppeared:
                    queue.Enqueue(filePacket);
                    if (queue.EnqueueAddedFirstAvailableItem)     // If it is a first awailable packet in the queue, setting the signal to the consumer
                    {
                        eventForFirstPacketInQueue.Set();
                    }
                    if (eventType == EventsForProducer.SpaceAppeared && !queue.HaveSpace())
                    {
                        eventForNewSpaceInQueue.Reset();     // Resetting our signal of new space appearance
                    }
                    break;

                case EventsForProducer.Cancel:
                    cancel = true;
                    break;

                default:
                    Debug.Write($"Unsupported event type for producer: {Enum.GetName(typeof(EventsForProducer), eventType)}");
                    break;
                }
            }
            finally
            {
                if (taken)
                {
                    mutex.ReleaseMutex();
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Consuming the next piece of uncompressed file
        /// </summary>
        /// <param name="cancel">Cancellation flag</param>
        public FilePacketMemoryStream Consume(out bool cancel)
        {
            FilePacketMemoryStream result = null;

            var taken = true;

            mutex.WaitOne();
            try
            {
                cancel = cancelled;
                if (cancel)
                {
                    return(result);
                }

                var eventType = EventsForConsumer.PacketsExists;
                // If queue if empty, begin to await for it's replenishment
                while (queueFilledCount == 0 && !readCompleted)
                {
                    taken = false;
                    mutex.ReleaseMutex();

                    eventType = (EventsForConsumer)WaitHandle.WaitAny(eventsForConsumer);
                    mutex.WaitOne();
                    taken = true;

                    if ((eventType == EventsForConsumer.PacketAppeared && queueFilledCount != 0) ||
                        eventType == EventsForConsumer.ReadCompleted ||
                        eventType == EventsForConsumer.Cancel)
                    {
                        break;
                    }
                }
                if (queueFilledCount == 0 && readCompleted)
                {
                    return(result);
                }
                switch (eventType)
                {
                case EventsForConsumer.PacketsExists:
                case EventsForConsumer.PacketAppeared:
                    result = Dequeue();
                    if (queueFilledCount == queueDepth - 1)     // If there is new free space appeared in the queue, signaling producer about it
                    {
                        eventForNewSpaceInQueue.Set();
                    }
                    if (eventType == EventsForConsumer.PacketAppeared && queueFilledCount == 0)
                    {
                        eventForFirstPacketInQueue.Reset();     // Resetting our signal about new packet appering
                    }
                    break;

                case EventsForConsumer.ReadCompleted:
                    // Do nothing, just below we'll return the empty pre-initialized result
                    break;

                case EventsForConsumer.Cancel:
                    cancel = true;
                    break;

                default:
                    Debug.Write($"Unsupported event type for consumer: {Enum.GetName(typeof(EventsForConsumer), eventType)}");
                    break;
                }
            }
            finally
            {
                if (taken)
                {
                    mutex.ReleaseMutex();
                }
            }

            return(result);
        }