libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

data_parallel.h (4338B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #ifndef LIB_JXL_BASE_DATA_PARALLEL_H_
      7 #define LIB_JXL_BASE_DATA_PARALLEL_H_
      8 
      9 // Portable, low-overhead C++11 ThreadPool alternative to OpenMP for
     10 // data-parallel computations.
     11 
     12 #include <jxl/parallel_runner.h>
     13 #include <stddef.h>
     14 #include <stdint.h>
     15 
     16 #include "lib/jxl/base/compiler_specific.h"
     17 #include "lib/jxl/base/status.h"
     18 #if JXL_COMPILER_MSVC
     19 // suppress warnings about the const & applied to function types
     20 #pragma warning(disable : 4180)
     21 #endif
     22 
     23 namespace jxl {
     24 
     25 class ThreadPool {
     26  public:
     27   ThreadPool(JxlParallelRunner runner, void* runner_opaque)
     28       : runner_(runner),
     29         runner_opaque_(runner ? runner_opaque : static_cast<void*>(this)) {}
     30 
     31   ThreadPool(const ThreadPool&) = delete;
     32   ThreadPool& operator&(const ThreadPool&) = delete;
     33 
     34   JxlParallelRunner runner() const { return runner_; }
     35   void* runner_opaque() const { return runner_opaque_; }
     36 
     37   // Runs init_func(num_threads) followed by data_func(task, thread) on worker
     38   // thread(s) for every task in [begin, end). init_func() must return a Status
     39   // indicating whether the initialization succeeded.
     40   // "thread" is an integer smaller than num_threads.
     41   // Not thread-safe - no two calls to Run may overlap.
     42   // Subsequent calls will reuse the same threads.
     43   //
     44   // Precondition: begin <= end.
     45   template <class InitFunc, class DataFunc>
     46   Status Run(uint32_t begin, uint32_t end, const InitFunc& init_func,
     47              const DataFunc& data_func, const char* caller = "") {
     48     JXL_ASSERT(begin <= end);
     49     if (begin == end) return true;
     50     RunCallState<InitFunc, DataFunc> call_state(init_func, data_func);
     51     // The runner_ uses the C convention and returns 0 in case of error, so we
     52     // convert it to a Status.
     53     if (!runner_) {
     54       void* jpegxl_opaque = static_cast<void*>(&call_state);
     55       if (call_state.CallInitFunc(jpegxl_opaque, 1) != 0) {
     56         return JXL_FAILURE("Failed to initialize thread");
     57       }
     58       for (uint32_t i = begin; i < end; i++) {
     59         call_state.CallDataFunc(jpegxl_opaque, i, 0);
     60       }
     61       return true;
     62     }
     63     return (*runner_)(runner_opaque_, static_cast<void*>(&call_state),
     64                       &call_state.CallInitFunc, &call_state.CallDataFunc, begin,
     65                       end) == 0;
     66   }
     67 
     68   // Use this as init_func when no initialization is needed.
     69   static Status NoInit(size_t num_threads) { return true; }
     70 
     71  private:
     72   // class holding the state of a Run() call to pass to the runner_ as an
     73   // opaque_jpegxl pointer.
     74   template <class InitFunc, class DataFunc>
     75   class RunCallState final {
     76    public:
     77     RunCallState(const InitFunc& init_func, const DataFunc& data_func)
     78         : init_func_(init_func), data_func_(data_func) {}
     79 
     80     // JxlParallelRunInit interface.
     81     static int CallInitFunc(void* jpegxl_opaque, size_t num_threads) {
     82       const auto* self =
     83           static_cast<RunCallState<InitFunc, DataFunc>*>(jpegxl_opaque);
     84       // Returns -1 when the internal init function returns false Status to
     85       // indicate an error.
     86       return self->init_func_(num_threads) ? 0 : -1;
     87     }
     88 
     89     // JxlParallelRunFunction interface.
     90     static void CallDataFunc(void* jpegxl_opaque, uint32_t value,
     91                              size_t thread_id) {
     92       const auto* self =
     93           static_cast<RunCallState<InitFunc, DataFunc>*>(jpegxl_opaque);
     94       return self->data_func_(value, thread_id);
     95     }
     96 
     97    private:
     98     const InitFunc& init_func_;
     99     const DataFunc& data_func_;
    100   };
    101 
    102   // The caller supplied runner function and its opaque void*.
    103   const JxlParallelRunner runner_;
    104   void* const runner_opaque_;
    105 };
    106 
    107 template <class InitFunc, class DataFunc>
    108 Status RunOnPool(ThreadPool* pool, const uint32_t begin, const uint32_t end,
    109                  const InitFunc& init_func, const DataFunc& data_func,
    110                  const char* caller) {
    111   if (pool == nullptr) {
    112     ThreadPool default_pool(nullptr, nullptr);
    113     return default_pool.Run(begin, end, init_func, data_func, caller);
    114   } else {
    115     return pool->Run(begin, end, init_func, data_func, caller);
    116   }
    117 }
    118 
    119 }  // namespace jxl
    120 #if JXL_COMPILER_MSVC
    121 #pragma warning(default : 4180)
    122 #endif
    123 
    124 #endif  // LIB_JXL_BASE_DATA_PARALLEL_H_