Jellyfish.Commands.Metrics.RollingPercentileNumber.GetCurrentBucket C# (CSharp) Method

GetCurrentBucket() private method

private GetCurrentBucket ( ) : Bucket
return Bucket
        internal Bucket GetCurrentBucket()
        {
            int newCurrentIndex;
            int initialCurrentIndex;
            Bucket bucket;
            Bucket newBucket;
            long currentTime;

            do
            {
                currentTime = clock.EllapsedTimeInMs;

                initialCurrentIndex = currentBucketIndex;
                bucket = buckets[initialCurrentIndex];
                if (bucket.bucketStartInMs + bucketSizeInMs > currentTime)
                {
                    return bucket;
                }

                newCurrentIndex = (currentBucketIndex + 1) % (numberOfBuckets + 1);
                newBucket = buckets[newCurrentIndex];

                bool lockTacken = false;
                try
                {
                    Monitor.TryEnter(gate, 10, ref lockTacken);                                     
                    if (!lockTacken)
                    {
                        return newBucket;
                    }
                    newBucket.Reset(currentTime);
                }
                finally
                {
                    if (lockTacken)
                        Monitor.Exit(gate);
                }
            }
            while (Interlocked.CompareExchange(ref currentBucketIndex, newCurrentIndex, initialCurrentIndex) != initialCurrentIndex);

            var items = from b in GetBuckets()
                          select new SnapshotItem { Length = b.Length, Data = b.data };
            _percentileSnapshot = new PercentileSnapshot(items.ToArray());

            return newBucket;
        }

Usage Example

        public void testWriteThreadSafety()
        {
            MockedClock time = new MockedClock();
            RollingPercentileNumber p = new RollingPercentileNumber(time, 100, 25, 1000, DynamicProperties.Factory.AsProperty(true));

            int NUM_THREADS = 10;
            int NUM_ITERATIONS = 1000;

            var tasks = new Task[NUM_THREADS];

            Random r = new Random();

            long added = 0;

            for (int i = 0; i < NUM_THREADS; i++)
            {
                tasks[i] = Task.Run(() =>
                {

                    for (int j = 1; j < NUM_ITERATIONS / NUM_THREADS + 1; j++)
                    {
                        int nextInt = r.Next(100);
                        p.AddValue(nextInt);
                        Interlocked.Increment(ref added);
                    }
                });
            }

            if (!Task.WaitAll(tasks, 1000))
                throw new Exception("Timeout on all threads writing percentiles");
            Assert.Equal(added, p.GetCurrentBucket().Length);

        }