private void PoolRunner(int iterations, ConcurrentRingBufferImpl <Data> pool) { for (int i = 0; i < iterations; i++) { Data data = pool.Pop(); Interlocked.Increment(ref data.Counter); pool.Push(data); } }
public void SingleThreadAccessTest(int size, bool prefill) { ConcurrentRingBufferImpl <Data> pool = new ConcurrentRingBufferImpl <Data>(size); pool.Initialize(() => new Data(), prefill); var distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.Equal(pool.Data.Count, distintValues); List <Data> list = new List <Data>(size); for (int x = 0; x < size; x++) { var item = pool.Pop(); item.Counter += 1; list.Add(item); } Assert.Equal(0, pool.Data.Count); for (int x = 0; x < size; x++) { pool.Push(list[x]); } foreach (var item in pool.Data) { item.tracked = false; } GC.Collect(2, GCCollectionMode.Forced); long totalUsage = 0; long totalCount = 0; foreach (var item in pool.Data) { if (item.Counter > 0) { totalUsage += 1; } totalCount += item.Counter; } Console.WriteLine("Counter:" + totalCount); Console.WriteLine("Usage:" + totalUsage); Console.WriteLine("Thrown away:" + Data.destroyed); distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.True(pool.Data.Count <= distintValues); Assert.True(size <= pool.Data.Count); }
public void ShouldNotBeAbleToPopFromAnEmptyBuffer(int size) { var evt = new ManualResetEvent(false); Thread t = new Thread(() => { var buffer = new ConcurrentRingBufferImpl <Data>(size); buffer.Initialize(() => new Data(), false); var data = buffer.Pop(); Assert.NotNull(data); }); t.Start(); if (evt.WaitOne(100)) { Assert.False(true, "Thread managed to pop from an empty buffer"); } }
public void TestSimplePopPush() { var pool1 = new ConcurrentRingBufferImpl <Data>(4); var pool2 = new ConcurrentRingBufferImpl <Data>(4); pool1.Initialize(() => new Data(), true); pool2.Initialize(() => new Data(), true); var quitEvent = new ManualResetEvent(false); var t1 = new Thread(() => { do { var item = pool1.Pop(); Thread.Sleep(TimeSpan.FromTicks(new Random(Thread.CurrentThread.ManagedThreadId).Next(5))); pool2.Push(item); }while (!quitEvent.WaitOne(1, true)); }); var t2 = new Thread(() => { do { var item = pool2.Pop(); Thread.Sleep(TimeSpan.FromTicks(new Random(Thread.CurrentThread.ManagedThreadId).Next(5))); pool1.Push(item); }while (!quitEvent.WaitOne(1, true)); }); t1.Start(); t2.Start(); Thread.Sleep(50); quitEvent.Set(); t1.Join(); t2.Join(); GC.Collect(2, GCCollectionMode.Forced); Console.WriteLine("Created:{0}", Data.numberCreated); Console.WriteLine("Thrown away:{0}", Data.destroyed); }
public void ShouldBeAbleToEmptyBufferCompletely(int size) { var buffer = new ConcurrentRingBufferImpl <Data>(size); buffer.Initialize(() => new Data(), false); List <Data> list = new List <Data>(); for (int x = 0; x < size; x++) { var data = new Data(); list.Add(data); buffer.Push(data); } for (int x = 0; x < size; x++) { Assert.True(list.Contains(buffer.Pop())); } }
public void MultiThreadedAccess(int size, bool prefill, int threadCount, int sleep) { ConcurrentRingBufferImpl <Data> pool = new ConcurrentRingBufferImpl <Data>(size); pool.Initialize(() => new Data(), prefill); var distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.Equal(pool.Data.Count, distintValues); int localCount = Math.Max(1, size / threadCount); List <Thread> threads = new List <Thread>(); ManualResetEvent startEvent = new ManualResetEvent(false); StringBuilder sb = new StringBuilder(); Console.WriteLine("Testing with:{0} items per thread", localCount); for (int y = 0; y < threadCount; y++) { var thread = new Thread(() => { var random = new Random(Thread.CurrentThread.ManagedThreadId); try { startEvent.WaitOne(); Thread.Sleep(TimeSpan.FromTicks(random.Next(5))); Stack <Data> list = new Stack <Data>(localCount); for (int x = 0; x < localCount; x++) { var item = pool.Pop(); item.SetOwner(); Thread.Sleep(TimeSpan.FromMilliseconds(random.Next(2) * sleep)); item.Counter += 1; list.Push(item); } // Assert that we got at least as many as we requested Assert.Equal(localCount, list.Count); for (int x = localCount - 1; x > -1; x--) { var item = list.Pop(); Thread.Sleep(TimeSpan.FromMilliseconds(random.Next(1))); item.ReleaseOwner(); pool.Push(item); } } catch (Exception e) { lock (sb) { sb.Append(e); } } }); threads.Add(thread); } threads.ForEach(t => t.Start()); startEvent.Set(); Parallel.ForEach(threads, t => t.Join(TimeSpan.FromSeconds(10))); if (sb.Length > 0) { Assert.True(false, sb.ToString()); } foreach (var item in pool.Data) { item.tracked = false; } GC.Collect(2, GCCollectionMode.Forced); long totalUsage = 0; long totalCount = 0; foreach (var item in pool.Data) { if (item.Counter > 0) { totalUsage += 1; } totalCount += item.Counter; } Console.WriteLine("Counter:" + totalCount); Console.WriteLine("Usage:" + totalUsage); Console.WriteLine("Thrown away:" + Data.destroyed); Console.WriteLine("Thrown away (pool):" + pool.ThrownAwayObjects); Console.WriteLine("Created (pool):" + pool.Created); distintValues = pool.Data.Distinct(new DataComparer()).Count(); Assert.True(pool.Data.Count <= distintValues); if (prefill) { // We cant know how many objects are created when we dont prefill pools if (threadCount <= size) { Assert.Equal(size, pool.ObjectsInPool); } } }