public void Execute(WorkerStep step)
 {
     lock (this)
     {
         Interlocked.Exchange(ref _batchIndex, -1); // -1 because Interlocked.Increment returns the *incremented* value
         _step = step;
         if (_outstandingWorkersNeedsSync != 0)
         {
             throw new InvalidOperationException("There are still outstanding workers!");
         }
         _outstandingWorkersNeedsSync = _workerCount;
     }
     for (int i = 1; i < _workerCount; i++) // the current thread will be worker 0
     {
         ThreadPool.QueueUserWorkItem(_executeImpl, this);
     }
     ExecuteImpl(); // lend a hand ourselves
     lock (this)
     {
         if (_outstandingWorkersNeedsSync != 0 && !Monitor.Wait(this, millisecondsTimeout: 10_000))
         {
             throw new TimeoutException("Timeout waiting for parallel workers to complete");
         }
     }
 }
Esempio n. 2
0
            private void Execute(WorkerStep step, int batchIndex, int start, int end)
            {
                int count = end - start;

                // Console.WriteLine($"{step}/{_shift}/{batchIndex}: [{start},{end}] ({count}) on thread {Environment.CurrentManagedThreadId}");

                switch (step)
                {
                case WorkerStep.Copy:
                    _keys.Span.Slice(start, count).CopyTo(_workspace.Span.Slice(start, count));
                    break;

                case WorkerStep.BucketCountAscending:
                case WorkerStep.BucketCountDescending:
                {
                    var keys    = _keys.Span.NonPortableCast <T, uint>();
                    var buckets = _countsOffsets.Span.NonPortableCast <T, uint>().Slice(
                        batchIndex * _bucketCount, _bucketCount);
                    if (step == WorkerStep.BucketCountAscending)
                    {
                        BucketCountAscending(buckets, keys, start, end, _shift, _groupMask);
                    }
                    else
                    {
                        BucketCountDescending(buckets, keys, start, end, _shift, _groupMask);
                    }
                }
                break;

                case WorkerStep.ApplyAscending:
                case WorkerStep.ApplyDescending:
                {
                    var offsets = _countsOffsets.Span.NonPortableCast <T, uint>().Slice(
                        batchIndex * _bucketCount, _bucketCount);
                    if (NeedsApply(offsets))
                    {
                        var keys      = _keys.Span.NonPortableCast <T, uint>();
                        var workspace = _workspace.Span.NonPortableCast <T, uint>();
                        if (step == WorkerStep.ApplyAscending)
                        {
                            ApplyAscending(offsets, keys, workspace, start, end, _shift, _groupMask);
                        }
                        else
                        {
                            ApplyDescending(offsets, keys, workspace, start, end, _shift, _groupMask);
                        }
                    }
                    else
                    {
                        _keys.Span.Slice(start, count).CopyTo(_workspace.Span.Slice((int)offsets[0], count));
                    }
                }
                break;

                default:
                    throw new NotImplementedException($"Unknown worker step: {step}");
                }
            }