/* * 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. * * Copyright 2018 Danny Robson */ #ifndef CRUFT_UTIL_JOB_DISPATCH_HPP #define CRUFT_UTIL_JOB_DISPATCH_HPP #include "queue.hpp" #include "../extent.hpp" #include "../region.hpp" #include namespace util::job { // call a function across all elements of a container using the supplied // job queue. // // threads will have work sizes dictated by a supplied extent. // // returns a cookie that will block at destruction until all jobs have // completed. it will take ownership of an forwarding-reference function // if one is supplied. // // TODO: extend to 1d and 3d template < typename ContainerT, typename FunctionT, typename ...Args, size_t DimensionV > auto dispatch ( util::job::queue &q, ContainerT &data, util::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; inner_data[p][0] = std::invoke (func, p, inner_args...); } }; std::vector cookies; const extent2i count = (data.extent () + chunk - 1) / chunk; for (auto index: count.step ()) { util::point base = index * chunk; cookies.push_back ( q.submit ( chunked_func, std::ref (data), util::region {base, chunk}.step (), args... ) ); } return std::tuple (std::forward (func), std::move (cookies)); } } #endif