Beispiel #1
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();
                }
            }
        }