#pragma once

#include <maps/libs/log8/include/log8.h>

#include <tbb/tbb.h>

#include <exception>
#include <mutex>

namespace maps::mrc::common {

/// exception-safe TBB wrapper
template <int MAX_THREADS = 8, class Iterator, class Functor>
void parallelForEach(Iterator first, Iterator last, const Functor& func)
{
    std::mutex guard;
    std::exception_ptr pendingError;
    tbb::global_control gc(tbb::global_control::max_allowed_parallelism,
                           MAX_THREADS);
    tbb::parallel_for_each(first, last, [&](auto&& item) {
        try {
            func(guard, item);
        }
        catch (const std::exception& e) {
            WARN() << e.what();
            std::lock_guard lock{guard};
            if (!pendingError) {
                pendingError = std::current_exception();
            }
        }
    });
    if (pendingError) {
        std::rethrow_exception(pendingError);
    }
}

}  // namespace maps::mrc::common
