Jump to content
  • Advertisement
Sign in to follow this  
Guthur

[C#] multithreaded double buffer critical evaluation

This topic is 3494 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have been tinkering with multithreading recently and I would like a little input on the following simple double buffer. Its not spectacular in any way, the wait to fill is probably the only novel feature, just would like a little peer review for constructive criticism and if possible to iron out any flaws. Usage scenario: Consumer 1; Producers Many;
using System;
using System.Timers;
using System.Threading;
using System.Collections.Generic;

namespace LittleEdge_Utility
{
    /// <summary>
    /// Summary description for mtBufferedDispatch
    /// </summary>
    public class mtBufferedDispatch<T>
    {
        const int SET = 1;
        const int UNSET = 0;

        Queue<T> BufferToFill;
        Queue<T> BufferToEmpty;

        int WaitToFill;
        int InitialBufferSize;

        //Signalled when new output is available for the consumer, auto resetting as there is only one consumer
        EventWaitHandle NewOutputSignal;
        //Signalled when a new output buffer can be made available, manually set when the output has been consumed
        EventWaitHandle OutputConsumed;
        //Signalled when operations can be made to the buffers, auto resetting so only one thread at a time can have access.
        EventWaitHandle AddingItemWait;

        System.Timers.Timer WaitToFillTimer;
        int TimerState = UNSET;

        public mtBufferedDispatch(int bufferSize, int waitToFill)
        {
            InitialBufferSize = bufferSize;
            WaitToFill = waitToFill;

            WaitToFillTimer = new System.Timers.Timer(WaitToFill);
            WaitToFillTimer.Elapsed += new ElapsedEventHandler(WaitToFillTimer_Elapsed);
            WaitToFillTimer.AutoReset = false;

            BufferToFill = new Queue<T>(InitialBufferSize);

            NewOutputSignal = new EventWaitHandle(false, EventResetMode.AutoReset);
            AddingItemWait = new EventWaitHandle(true, EventResetMode.AutoReset);
            OutputConsumed = new EventWaitHandle(true, EventResetMode.ManualReset);
        }

        void WaitToFillTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            OutputConsumed.WaitOne();
            AddingItemWait.WaitOne();

            BufferToEmpty = BufferToFill;
            OutputConsumed.Reset();
            NewOutputSignal.Set();
            
            BufferToFill = new Queue<T>(InitialBufferSize);
            AddingItemWait.Set();
            Interlocked.Exchange(ref TimerState, UNSET);
        }

        public void AddInput(T item)
        {            
            AddingItemWait.WaitOne();
            BufferToFill.Enqueue(item);
            AddingItemWait.Set();
            if (Interlocked.CompareExchange(ref TimerState, SET, UNSET) == UNSET)
            {
                WaitToFillTimer.Start();
            }
        }

        public bool WaitOnOutput(int wait)
        {
            return NewOutputSignal.WaitOne(wait);
        }

        public Queue<T> GetOutput
        {
            get
            {
                Queue<T> output = BufferToEmpty;
                OutputConsumed.Set();
                return output;
            }
        }
    }
}




Edit Note: I'm really still undecided on what is the best underlying container to use, the order of insertion maybe not be the same as order of creation which means I will have to sort any output, which is my current use case. Edit: minor change - started timer after adding an object, doh :) [Edited by - Guthur on May 21, 2009 6:14:29 PM]

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!