diff --git a/job/dispatch.hpp b/job/dispatch.hpp index fb0ecbde..dfb38e21 100644 --- a/job/dispatch.hpp +++ b/job/dispatch.hpp @@ -6,13 +6,13 @@ * Copyright 2018 Danny Robson */ -#ifndef CRUFT_UTIL_JOB_DISPATCH_HPP -#define CRUFT_UTIL_JOB_DISPATCH_HPP +#pragma once #include "queue.hpp" #include "../extent.hpp" #include "../region.hpp" +#include "../concepts.hpp" #include @@ -27,42 +27,54 @@ namespace cruft::job { /// if one is supplied. /// /// TODO: extend to 1d and 3d + /// + /// \param area The total size of the work unit + /// \param chunk The size of the subdivided units to be send to threads. template < typename ContainerT, typename FunctionT, - typename ...Args, + typename ...ArgsT, size_t DimensionV > + requires requires ( + ContainerT t, + cruft::point p, + FunctionT f, + ArgsT ...args + ) { + { t[p] = std::invoke (f, p, args...) }; + } auto dispatch ( cruft::job::queue &q, ContainerT &data, + cruft::region total_area, cruft::extent chunk, FunctionT &&func, - Args ...args) - { - auto chunked_func = [&func] (ContainerT &inner_data, - auto param, - Args... inner_args) - { - for (auto p: param) { - if (!inner_data.extent ().exclusive (p)) - continue; + ArgsT ...args + ) { + auto chunked_func = [&func] ( + ContainerT &inner_data, + auto param, + ArgsT... inner_args + ) { + for (cruft::point p: param) inner_data[p] = std::invoke (func, p, inner_args...); - } }; std::vector cookies; - const extent2i count = (data.extent () + chunk - 1) / chunk; + extent2i const count = (total_area.e + chunk - 1) / chunk; for (auto index: count.step ()) { - cruft::point base = index * chunk; + cruft::point base = index * chunk + total_area.p.template as (); + region const oversized_work { base, chunk }; + auto const constrained_work = intersection (oversized_work, total_area); cookies.push_back ( q.submit ( chunked_func, std::ref (data), - cruft::region {base, chunk}.step (), + constrained_work.step (), args... ) ); @@ -71,5 +83,3 @@ namespace cruft::job { return std::tuple (std::forward (func), std::move (cookies)); } } - -#endif diff --git a/test/job/dispatch.cpp b/test/job/dispatch.cpp index fceb28e5..8a1ced06 100644 --- a/test/job/dispatch.cpp +++ b/test/job/dispatch.cpp @@ -14,39 +14,53 @@ /////////////////////////////////////////////////////////////////////////////// -struct value { - template - void operator= (T &&) { } -}; +struct container { + cruft::point2i + operator[] (cruft::point2i p)& + { return values.emplace_back () = p; } + bool is_unique (void) + { + cruft::coord::ordering comp {}; + std::sort (values.begin (), values.end (), comp); + auto const pos = std::adjacent_find (values.begin (), values.end ()); + return pos == values.end (); + } -//----------------------------------------------------------------------------- -struct data_t { - cruft::extent2i extent (void) const { return { 4, 4 }; } - auto operator[] (cruft::point2i) { return value {};}; + std::size_t size (void) const { return values.size (); } + + std::vector values; }; //----------------------------------------------------------------------------- void test_dispatch_uniqueness (cruft::TAP::logger &tap) { - std::vector points; - data_t data; + container store; + + cruft::region2i const work_region { + cruft::point2i { 0 }, + cruft::extent2i { 512 } + }; cruft::job::queue q (1, 512 * 512 + 1); cruft::job::dispatch ( - q, data, + q, store, + work_region, cruft::extent2i {2}, - [&] (cruft::point2i p) - { - points.push_back (p); - return 0; - }); + [] (auto &&arg) { return arg; } + ); - cruft::coord::ordering comp {}; - std::sort (points.begin (), points.end (), comp); - auto const pos = std::adjacent_find (points.begin (), points.end ()); - tap.expect (pos == points.end (), "job::queue indices are unique"); + tap.expect ( + store.is_unique (), + "job::queue indices are unique" + ); + + tap.expect_eq ( + store.size (), + std::size_t (work_region.magnitude ().area ()), + "job::queue evaluated expected times" + ); }