/// <summary> /// Initializes a new instance. /// </summary> /// <param name="index">The zero-based index of the worker.</param> /// <param name="context">The context the model is traversed in.</param> /// <param name="stateStack">The state stack that should be used by the worker.</param> /// <param name="model">The model that the worker should analyze.</param> public Worker(int index, TraversalContext context, StateStack stateStack, AnalysisModel model) { Requires.NotNull(context, nameof(context)); Requires.NotNull(stateStack, nameof(stateStack)); Requires.NotNull(model, nameof(model)); _index = index; _context = context; _stateStack = stateStack; Model = model; }
/// <summary> /// Initializes a new instance. /// </summary> /// <param name="stacks"></param> public LoadBalancer(StateStack[] stacks) { _stacks = stacks; Reset(); }
/// <summary> /// Splits the work between this instance and the <paramref name="other" /> instance. Returns <c>true</c> to indicate that /// work has been split; <c>false</c>, otherwise. /// </summary> /// <param name="other">The other instance the work should be split with.</param> public bool SplitWork(StateStack other) { Assert.That(CanSplit, "Cannot split the state stack."); Assert.That(other.FrameCount == 0, "Expected an empty state stack."); // We go through each frame and split the first frame with more than two states in half for (var i = 0; i < FrameCount; ++i) { other.PushFrame(); switch (_frames[i].Count) { // The stack is in an invalid state; clear the other worker's stack and let this worker // continue; it will clean up its stack and try to split work later case 0: other.Clear(); return false; // We can't split work here, so just push the state to the other worker's stack case 1: other.PushState(_states[_frames[i].Offset]); break; // We've encountered a frame where we can actually split work; we always split work as early as possible, // that is, as low on the stack as possible, to hopefully maximize the amount of work passed to the other worker default: // Split the states of the frame var otherCount = _frames[i].Count / 2; var thisCount = _frames[i].Count - otherCount; // Add the first otherCount states to the other stack for (var j = 0; j < otherCount; ++j) other.PushState(_states[_frames[i].Offset + j]); // Adjust the count and offset of the frame _frames[i].Offset += otherCount; _frames[i].Count = thisCount; // Find the next splittable frame if this one no longer is if (thisCount == 1) UpdateLowestSplittableFrame(); return true; } } // This stack could not be split, so we clear the other's stack and let some other worker try again other.Clear(); return false; }