Beispiel #1
0
		/// <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;
		}
Beispiel #2
0
		/// <summary>
		///   Initializes a new instance.
		/// </summary>
		/// <param name="stacks"></param>
		public LoadBalancer(StateStack[] stacks)
		{
			_stacks = stacks;
			Reset();
		}
Beispiel #3
0
		/// <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;
		}