private async Task ReleaseBucketImpl(SerialExecutionBucket bucket, bool isAsync)
        {
            using (isAsync ? await _lockAsync.LockAsync()
                           : _lockAsync.Lock())
            {
                var resource = bucket.Resource;

                //reads bucket from dictionary again
                var bucketInDict = _buckets.ContainsKey(resource) ? _buckets[resource] : null;

                if (object.ReferenceEquals(bucket, bucketInDict))
                {
                    _buckets.Remove(resource);
                }
            }
        }
        private async Task RunImpl(Guid resource, Func <Task> factory, CancellationToken cancellationToken, bool isAsync)
        {
            SerialExecutionBucket bucket = null;
            bool run = false;

            while (!run)
            {
                using (isAsync ? await _lockAsync.LockAsync(cancellationToken)
                               : _lockAsync.Lock(cancellationToken))
                {
                    bucket = _buckets.ContainsKey(resource) ? _buckets[resource]
                                        : (_buckets[resource] = SerialExecutionBucket.Create(resource));
                }

                run = isAsync ? await bucket.RunImpl(factory, ReleaseBucketTask, cancellationToken, isAsync : isAsync)
                               : SyncTaskHelper.ValidateSyncTask(bucket.RunImpl(factory, ReleaseBucketSync, cancellationToken, isAsync: isAsync));
            }
        }
 private Task ReleaseBucketSync(SerialExecutionBucket bucket)
 {
     return(ReleaseBucketImpl(bucket, isAsync: false));
 }
 private async Task ReleaseBucketTask(SerialExecutionBucket bucket)
 {
     await ReleaseBucketImpl(bucket, isAsync : true);
 }