Exemple #1
0
 // construct the blocking queue
 public BlockingQueue_(int size)
 {
     queueSize   = size;
     room        = new T[size];
     putIdx      = takeIdx = 0;
     freeSlots   = new SemaphoreAsync(size, size);
     filledSlots = new SemaphoreAsync(0, size);
 }
Exemple #2
0
        // test semaphore as a mutual exclusion lock using asynchronous acquires
        private static bool TestSemaphoreAsLockAsync()
        {
            const int SETUP_TIME  = 50;
            const int RUN_TIME    = 5 * 1000;
            int       THREADS     = 20;
            const int MIN_TIMEOUT = 1;
            const int MAX_TIMEOUT = 50;

            Thread[]             tthrs           = new Thread[THREADS];
            int[]                privateCounters = new int[THREADS];
            int[]                timeouts        = new int[THREADS];
            int[]                cancellations   = new int[THREADS];
            int                  sharedCounter   = 0;
            bool                 exit            = false;
            ManualResetEventSlim start           = new ManualResetEventSlim();

#if USE_OUR_SEMAPHORE
            var _lock = new SemaphoreAsync(1, 1);       // our semaphore
#else
            SemaphoreSlim _lock = new SemaphoreSlim(1); // BCL semaphore
#endif

            //
            // Create and start acquirer/releaser threads
            //

            for (int i = 0; i < THREADS; i++)
            {
                int tid = i;
                tthrs[i] = new Thread(() => {
                    //Console.WriteLine("->#{0}", tid);
                    start.Wait();
                    Random rnd = new Random(tid);
                    do
                    {
                        do
                        {
                            using (CancellationTokenSource cts = new CancellationTokenSource())
                            {
                                try
                                {
                                    var resultTask = _lock.WaitAsync(rnd.Next(MAX_TIMEOUT), cts.Token);
                                    if (rnd.Next(100) < 10)
                                    {
                                        cts.Cancel();
                                    }
                                    if (resultTask.Result)
                                    {
                                        break;
                                    }
                                    timeouts[tid]++;
                                }
                                catch (AggregateException ae)
                                {
                                    ae.Handle((e) => {
                                        if (e is TaskCanceledException)
                                        {
                                            cancellations[tid]++;
                                            return(true);
                                        }
                                        return(false);
                                    });
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine("*** Exception type: {0}", ex.GetType());
                                }
                            }
                        } while (true);
                        sharedCounter++;
                        if (THREADS > 1)
                        {
                            if (rnd.Next(100) < 95)
                            {
                                Thread.Yield();
                            }
                            else
                            {
                                Thread.Sleep(rnd.Next(MIN_TIMEOUT, MAX_TIMEOUT));
                            }
                        }
                        privateCounters[tid]++;
                        _lock.Release();
                        if (THREADS > 1 && privateCounters[tid] % 100 == 0)
                        {
                            Console.Write("[#{0:D2}]", tid);
                        }
                    } while (!Volatile.Read(ref exit));
                    //Console.Write("\n<-#{0}", tid);
                });
                tthrs[i].Start();
            }

            Thread.Sleep(SETUP_TIME);
            Stopwatch sw = Stopwatch.StartNew();
            start.Set();
            int endTime = Environment.TickCount + RUN_TIME;
            //...
            do
            {
                Thread.Sleep(20);
                if (Console.KeyAvailable)
                {
                    Console.Read();
                    break;
                }
            } while (Environment.TickCount < endTime);
            Volatile.Write(ref exit, true);
            int sharedSnapshot = Volatile.Read(ref sharedCounter);
            sw.Stop();
            // Wait until all threads have been terminated.
            for (int i = 0; i < THREADS; i++)
            {
                tthrs[i].Join();
            }

            // Compute results

            Console.WriteLine("\n\nPrivate counters:");
            int sum = 0;
            for (int i = 0; i < THREADS; i++)
            {
                sum += privateCounters[i];
                if (i != 0 && i % 3 == 0)
                {
                    Console.WriteLine();
                }
                else if (i != 0)
                {
                    Console.Write(' ');
                }
                Console.Write("[#{0:D2}: {1}/{2}/{3}]", i, privateCounters[i], timeouts[i], cancellations[i]);
            }
            Console.WriteLine();
            long unitCost = (sw.ElapsedMilliseconds * 1000000L) / sharedSnapshot;
            Console.WriteLine("--unit cost of acquire/release: {0} {1}",
                              unitCost > 1000 ? unitCost / 1000 : unitCost,
                              unitCost > 1000 ? "us" : "ns");
            return(sum == sharedCounter);
        }
Exemple #3
0
        // test semaphore fairness asynchronous
        private static bool TestSemaphoreFairnessAsync()
        {
            const int SETUP_TIME  = 50;
            const int THREADS     = 50;
            const int MIN_TIMEOUT = 5;
            const int MAX_TIMEOUT = 20;

            Thread[]             tthrs           = new Thread[THREADS];
            int[]                privateCounters = new int[THREADS];
            ManualResetEventSlim startEvent      = new ManualResetEventSlim(false);
            var  sem           = new SemaphoreAsync(THREADS, THREADS);
            int  totalTimeouts = 0;
            bool exit          = false;

            for (int i = 0; i < THREADS; i++)
            {
                int tid = i;
                tthrs[i] = new Thread(() => {
                    Random random = new Random(tid);

                    // Wait until start event is set
                    startEvent.Wait();

                    do
                    {
                        do
                        {
                            if (sem.WaitAsyncEx(random.Next(MIN_TIMEOUT, MAX_TIMEOUT),
                                                CancellationToken.None).Result)
                            {
                                break;
                            }
                            Interlocked.Increment(ref totalTimeouts);
                        } while (true);
                        Thread.Yield();
                        sem.Release();
                        if ((++privateCounters[tid] % 100) == 0)
                        {
                            Console.Write("[#{0}]", tid);
                        }
                    } while (!Volatile.Read(ref exit));
                });
                tthrs[i].Start();
            }

            // Wait until all test threads have been started and then set the
            // start event.
            Thread.Sleep(SETUP_TIME);
            startEvent.Set();

            do
            {
                Thread.Sleep(50);
            } while (!Console.KeyAvailable);
            Console.Read();
            Volatile.Write(ref exit, true);

            // Wait until all threads have been terminated.
            for (int i = 0; i < THREADS; i++)
            {
                tthrs[i].Join();
            }

            // Show results
            int total = 0;

            Console.WriteLine("\nPrivate counters:");
            for (int i = 0; i < THREADS; i++)
            {
                if (i != 0 && (i % 5) == 0)
                {
                    Console.WriteLine();
                }
                Console.Write("[#{0:D2}:{1,4}]", i, privateCounters[i]);
                total += privateCounters[i];
            }
            Console.WriteLine("\n-- total acquisitions/releases: {0}, timeouts: {1}", total, totalTimeouts);
            return(true);
        }
Exemple #4
0
        // test semaphore as a mutual exclusion lock using synchronous acquires
        private static bool TestSemaphoreAsLock()
        {
            const int SETUP_TIME          = 50;
            const int RUN_TIME            = 10 * 1000;
            int       THREADS             = 20;
            const int MIN_TIMEOUT         = 0;
            const int MAX_TIMEOUT         = 10;
            const int MIN_CANCEL_INTERVAL = 10;
            const int MAX_CANCEL_INTERVAL = 50;

            Thread[]             tthrs            = new Thread[THREADS];
            int[]                privateCounters  = new int[THREADS];
            int[]                timeouts         = new int[THREADS];
            int[]                cancellations    = new int[THREADS];
            int[]                issuedInterrupts = new int[THREADS];
            int[]                sensedInterrupts = new int[THREADS];
            int                  sharedCounter    = 0;
            bool                 exit             = false;
            ManualResetEventSlim start            = new ManualResetEventSlim();

            // the semaphore
#if USE_OUR_SEMAPHORE
            var _lock = new SemaphoreAsync(1, 1);       // our semaphore
#else
            SemaphoreSlim _lock = new SemaphoreSlim(1); // BCL semaphore
#endif
            //
            // Create and start acquirer/releaser threads
            //

            for (int i = 0; i < THREADS; i++)
            {
                int tid = i;
                tthrs[i] = new Thread(() => {
                    Random rnd = new Random(Thread.CurrentThread.ManagedThreadId);
                    start.Wait();
                    CancellationTokenSource cts =
                        new CancellationTokenSource(rnd.Next(MIN_CANCEL_INTERVAL, MAX_CANCEL_INTERVAL));
                    do
                    {
                        do
                        {
                            try
                            {
                                if (_lock.Wait(rnd.Next(MIN_TIMEOUT, MAX_TIMEOUT), cts.Token))
                                {
                                    break;
                                }
                                timeouts[tid]++;
                            }
                            catch (OperationCanceledException)
                            {
                                cancellations[tid]++;
                                cts.Dispose();
                                cts = new CancellationTokenSource(rnd.Next(MIN_CANCEL_INTERVAL, MAX_CANCEL_INTERVAL));
                            }
                            catch (ThreadInterruptedException)
                            {
                                sensedInterrupts[tid]++;
                            }
                        } while (true);
                        sharedCounter++;
                        if (THREADS > 1)
                        {
                            if (rnd.Next(100) < 95)
                            {
                                Thread.Yield();
                            }
                            else
                            {
                                try
                                {
                                    Thread.Sleep(rnd.Next(MIN_TIMEOUT, MAX_TIMEOUT));
                                }
                                catch (ThreadInterruptedException)
                                {
                                    sensedInterrupts[tid]++;
                                }
                            }
                        }
                        // release the lock filtering interrupts
                        do
                        {
                            try
                            {
                                _lock.Release();
                                break;
                            }
                            catch (ThreadInterruptedException)
                            {
                                sensedInterrupts[tid]++;
                            }
                        } while (true);
                        privateCounters[tid]++;
                        if (THREADS > 1)
                        {
                            try
                            {
                                if ((privateCounters[tid] % 100) == 0)
                                {
                                    Console.Write("[#{0:D2}]", tid);
                                }
                            }
                            catch (ThreadInterruptedException)
                            {
                                sensedInterrupts[tid]++;
                            }
                        }
                    } while (!Volatile.Read(ref exit));
                    try
                    {
                        Thread.Sleep(100);
                    }
                    catch (ThreadInterruptedException)
                    {
                        sensedInterrupts[tid]++;
                    }
                });
                tthrs[i].Start();
            }
            Thread.Sleep(SETUP_TIME);
            Stopwatch sw = Stopwatch.StartNew();
            start.Set();
            Random grnd    = new Random(Thread.CurrentThread.ManagedThreadId);
            int    endTime = Environment.TickCount + RUN_TIME;
            //...
            do
            {
                Thread.Sleep(grnd.Next(100));
                if (THREADS > 1)
                {
                    var tid = grnd.Next(THREADS);
                    tthrs[tid].Interrupt();
                    issuedInterrupts[tid]++;
                }
                if (Console.KeyAvailable)
                {
                    Console.Read();
                    break;
                }
            } while (Environment.TickCount < endTime);
            Volatile.Write(ref exit, true);
            int sharedSnapshot = Volatile.Read(ref sharedCounter);
            sw.Stop();
            // Wait until all threads have been terminated.
            for (int i = 0; i < THREADS; i++)
            {
                tthrs[i].Join();
            }

            // Compute results

            Console.WriteLine("\nPrivate counters:");
            int sum = 0, sumInterrupts = 0, totalIssuedInterrupts = 0;
            for (int i = 0; i < THREADS; i++)
            {
                sum                   += privateCounters[i];
                sumInterrupts         += sensedInterrupts[i];
                totalIssuedInterrupts += issuedInterrupts[i];
                if (i != 0 && (i % 3) == 0)
                {
                    Console.WriteLine();
                }
                else if (i != 0)
                {
                    Console.Write(' ');
                }
                Console.Write("[#{0:D2}: {1}/{2}/{3}/{4}]", i,
                              privateCounters[i], timeouts[i], cancellations[i], sensedInterrupts[i]);
            }
            Console.WriteLine("\n--shared/private: {0}/{1}", sharedCounter, sum);
            Console.WriteLine("--interrupts issuded/sensed: {0}/{1}", totalIssuedInterrupts, sumInterrupts);
            long unitCost = (sw.ElapsedMilliseconds * 1000000L) / sharedSnapshot;

            Console.Write("--time per acquisition/release: {0} {1}",
                          unitCost >= 1000 ? unitCost / 1000 : unitCost,
                          unitCost >= 1000 ? "us" : "ns");
            for (var i = 0; i < THREADS; ++i)
            {
                Console.WriteLine($"issued:{issuedInterrupts[i]}, sensed:{sensedInterrupts[i]}");
            }
            return(sum == sharedCounter && totalIssuedInterrupts == sumInterrupts);
        }