Yarn: Add Utils.hpp

Currently only implements the parallelize() function - useful for evenly distributing workloads across threads.

Bug: b/139010488
Change-Id: I7c5705a46afadf137a0cf7fd517b61027ac3a239
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/34819
Tested-by: Ben Clayton <bclayton@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Yarn/Utils.hpp b/src/Yarn/Utils.hpp
new file mode 100644
index 0000000..87744d5
--- /dev/null
+++ b/src/Yarn/Utils.hpp
@@ -0,0 +1,54 @@
+// Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef yarn_util_hpp
+#define yarn_util_hpp
+
+#include "Scheduler.hpp"
+#include "WaitGroup.hpp"
+
+namespace yarn {
+
+// parallelize() is used to split a number of work items into N smaller batches
+// which can be processed in parallel with the function f().
+// numTotal is the total number of work items to process.
+// numPerTask is the maximum number of work items to process per call to f().
+// There will always be at least one call to f().
+// F must be a function with the signature:
+//    void(COUNTER taskIndex, COUNTER first, COUNTER count)
+// COUNTER is any integer type.
+template <typename F, typename COUNTER>
+inline void parallelize(COUNTER numTotal, COUNTER numPerTask, const F& f)
+{
+    auto numTasks = (numTotal + numPerTask - 1) / numPerTask;
+    WaitGroup wg(numTasks - 1);
+    for (unsigned int task = 1; task < numTasks; task++)
+    {
+        schedule([=] {
+            auto first = task * numPerTask;
+            auto count = std::min(first + numPerTask, numTotal) - first;
+            f(task, first, count);
+            wg.done();
+        });
+    }
+
+    // Run the first chunk on this fiber to reduce the amount of time spent
+    // waiting.
+    f(0, 0, std::min(numPerTask, numTotal));
+    wg.wait();
+}
+
+} // namespace yarn
+
+#endif // yarn_util_hpp