[英]Is there a way to write generic code for any function such that it can be executed (asyncronously) and a return value obtained from a thread pool?
我一直在嘗試創建線程池類(用於個人實驗/使用/娛樂)。 我找到了一種方法,可以使用參數包(在下面的代碼中看到)來接受具有任何參數/返回類型的任何函數,並將這些函數綁定到std :: function。 這沒有問題。 問題是我想嘗試使成員函數從正在執行的作業中檢索返回的值。 在執行此操作時,我不知道如何使代碼通用。
到目前為止,我已經嘗試制作一個地圖,該地圖使用作業ID作為鍵,並將該作業的返回值存儲在其中。 我的奮斗是1.我無法弄清楚如何確定類型(我可以使用“ typename std :: invoke_result :: type”,但是如果類型為空,則無法使用)2.如何制作可以擁有工作的地圖ID作為鍵和任何類型,以便我可以在其中放置返回類型。
class ThreadPool{
public:
//getInstance to allow the second constructor to be called
static ThreadPool& getInstance(int numThreads){
static ThreadPool instance(numThreads);
return instance;
}
//add any arg # function to queue
template <typename Func, typename... Args >
inline uint64_t push(Func& f, Args&&... args){
auto funcToAdd = std::bind(f, args...);
uint64_t newID = currentID++;
std::unique_lock<std::mutex> lock(JobMutex);
JobQueue.push(std::make_pair(funcToAdd, newID));
thread.notify_one();
return newID; //return the ID of the job in the queue
}
/* utility functions will go here*/
inline void resize(int newTCount){
int tmp = MAX_THREADS;
if(newTCount > tmp || newTCount < 1){
throw bad_thread_alloc("Cannot allocate " + std::to_string(newTCount) + " threads because it is greater than your systems maximum of " + std::to_string(tmp), __FILE__, __LINE__);
}
numThreads = (uint8_t)newTCount;
Pool.resize(newTCount);
DEBUG("New size is: " + std::to_string(Pool.size()));
}
inline uint8_t getThreadCount(){
return numThreads;
}
//how i want the user to interact with this class is
// int id = push(func, args);
// auto value = getReturnValue(id); //blocks until return value is returned
auto getReturnValue(uint64_t jobID) {
//Not sure how to handle this
}
private:
uint64_t currentID;
uint8_t numThreads;
std::vector<std::thread> Pool; //the actual thread pool
std::queue<std::pair<std::function<void()>, uint64_t>> JobQueue; //the jobs with their assigned ID
std::condition_variable thread;
std::mutex JobMutex;
/* infinite loop function */
void threadManager();
/* Constructors */
ThreadPool(); //prevent default constructor from being called
//real constructor that is used
inline ThreadPool(uint8_t numThreads) : numThreads(numThreads) {
currentID = 0; //initialize currentID
int tmp = MAX_THREADS;
if(numThreads > tmp){
throw bad_thread_alloc("Cannot allocate " + std::to_string(numThreads) + " threads because it is greater than your systems maximum of " + std::to_string(tmp), __FILE__, __LINE__);
}
for(int i = 0; i != numThreads; ++i){
Pool.push_back(std::thread(&ThreadPool::threadManager, this));
Pool.back().detach();
DEBUG("Thread " + std::to_string(i) + " allocated");
}
DEBUG("Number of threads being allocated " + std::to_string(numThreads));
}
/* end constructors */
NULL_COPY_AND_ASSIGN(ThreadPool);
}; /* end ThreadPool Class */
void ThreadPool::threadManager(){
while (true) {
std::unique_lock<std::mutex> lock(JobMutex);
thread.wait(lock, [this] {return !JobQueue.empty(); });
//strange bug where it will continue even if the job queue is empty
if (JobQueue.size() < 1)
continue;
auto job = JobQueue.front().first;
JobQueue.pop();
job();
}
}
我要解決所有這些錯誤嗎? 我不知道有什么其他方法可以通用地存儲任何類型的函數,同時還可以從中獲取返回類型。
提供一個位置來存儲返回值到創建作業的函數。 如果我們將返回位置與其他元素一起提供,那么在哪里存儲作業就沒有任何不確定性。
我們可以相對簡單地設計界面的這一部分。 如果將參數與函數打包在一起,則可以將所有排隊的作業存儲為std::function<void()>
。 這簡化了線程隊列的實現,因為線程隊列僅需要擔心一種類型的std::function
,而不必關心返回值。
using job_t = std::function<void()>;
template<class Return, class Func, class... Args>
job_t createJob(Return& dest, Func&& func, Args&&... args) {
return job_t([=]() {
dest = func(std::forward<Args>(args)...);
});
};
此實現使輕松地隨意啟動作業變得容易,而線程池不必擔心返回值的存儲位置。 例如,我編寫了一個運行作業的函數。 該函數在新線程上啟動作業,並在該函數完成時將atomic_bool
標記為true
。 因為我們不必擔心返回值,所以該函數只需將shared_ptr
返回給我們用來檢查函數是否完成的atomic_bool
。
using std::shared_ptr;
using std::atomic_bool;
shared_ptr<atomic_bool> run_job_async(std::function<void()> func) {
shared_ptr<atomic_bool> is_complete = std::make_shared<atomic_bool>(false);
std::thread t([f = std::move(func), =]() {
f();
*is_complete = true;
});
t.detach();
return is_complete;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.