// Copyright 2026 DeepMind Technologies Limited // // 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 MUJOCO_SRC_USER_USER_THREADPOOL_H_ #define MUJOCO_SRC_USER_USER_THREADPOOL_H_ #include #include #include #include #include #include #include namespace mujoco::user { // ThreadPool class class ThreadPool { public: // constructor explicit ThreadPool(int num_threads); // destructor ~ThreadPool(); int NumThreads() const { return threads_.size(); } // returns an ID between 0 and NumThreads() - 1. must be called within // worker thread (returns -1 if not). static int WorkerId() { return worker_id_; } // ----- methods ----- // // set task for threadpool void Schedule(std::function task); // return number of tasks completed std::uint64_t GetCount() { std::lock_guard lock(m_); return ctr_; } // reset count to zero void ResetCount() { std::lock_guard lock(m_); ctr_ = 0; } // wait for count, then return void WaitCount(int value) { std::unique_lock lock(m_); cv_ext_.wait(lock, [&]() { return ctr_ >= value; }); } private: // ----- methods ----- // // execute task with available thread void WorkerThread(int i); constinit static thread_local int worker_id_; // ----- members ----- // std::vector threads_; std::mutex m_; std::condition_variable cv_in_; std::condition_variable cv_ext_; std::queue> queue_; std::uint64_t ctr_; }; } // namespace mujoco::user #endif // MUJOCO_SRC_USER_USER_THREADPOOL_H_