안녕에 세그 폴트. 작업을 처리 할 수있는 스레드 풀을 만들려고합니다. 관련된 테스트 메인 아래에 있습니다.C++ 동시성</p> <p>내가 C 아주 새로운 오전 ++하지만 육년 자바 경험, 2 년 C 경험과 동시성 몇 가지 기본 지식을 가지고, 뮤텍스
내 디버거에 의해 말했듯이 오류가
void ThreadPool::ThreadHandler::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(queueMutex);
에서 생성되지만 기존의 cout을 디버그하고, 나는 때때로 segfaulting으로부터
threads.emplace(handler->getSize(), handler);
를 제거하지 않고 작동하는지 발견 것 같아 ThreadPool::enqueueTask()
은 안정성을 크게 향상시킵니다.
전반적으로 나는 conditioner_variable (idler라고 불리는)의 나쁜 사용과 관련이 있다고 생각합니다.
컴파일러 : CLion에서는 MinGW-W64
#include <iostream>
#include "ThreadPool.h"
ThreadPool::ThreadHandler::ThreadHandler(ThreadPool *parent) : parent(parent) {
thread = std::thread([&]{
while (this->parent->alive){
if (getSize()){
std::lock_guard<std::mutex> lock(queueMutex);
(*(queue.front()))();
queue.pop_front();
} else {
std::unique_lock<std::mutex> lock(idlerMutex);
idler.wait(lock);
}
}
});
}
void ThreadPool::ThreadHandler::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(queueMutex);
queue.push_back(task);
idler.notify_all();
}
size_t ThreadPool::ThreadHandler::getSize() {
std::lock_guard<std::mutex> lock(queueMutex);
return queue.size();
}
void ThreadPool::enqueueTask(void (*task)(void)) {
std::lock_guard<std::mutex> lock(threadsMutex);
std::map<int, ThreadHandler*>::iterator iter = threads.begin();
threads.erase(iter);
ThreadHandler *handler = iter->second;
handler->enqueueTask(task);
threads.emplace(handler->getSize(), handler);
}
ThreadPool::ThreadPool(size_t size) {
for (size_t i = 0; i < size; ++i) {
std::lock_guard<std::mutex> lock(threadsMutex);
ThreadHandler *handler = new ThreadHandler(this);
threads.emplace(handler->getSize(), handler);
}
}
ThreadPool::~ThreadPool() {
std::lock_guard<std::mutex> lock(threadsMutex);
auto it = threads.begin(), end = threads.end();
for (; it != end; ++it) {
delete it->second;
}
}
.H
#ifndef WLIB_THREADPOOL_H
#define WLIB_THREADPOOL_H
#include <mutex>
#include <thread>
#include <list>
#include <map>
#include <condition_variable>
class ThreadPool {
private:
class ThreadHandler {
std::condition_variable idler;
std::mutex idlerMutex;
std::mutex queueMutex;
std::thread thread;
std::list<void (*)(void)> queue;
ThreadPool *parent;
public:
ThreadHandler(ThreadPool *parent);
void enqueueTask(void (*task)(void));
size_t getSize();
};
std::multimap<int, ThreadHandler*> threads;
std::mutex threadsMutex;
public:
bool alive = true;
ThreadPool(size_t size);
~ThreadPool();
virtual void enqueueTask(void (*task)(void));
};
#endif //WLIB_THREADPOOL_H
주요 통화 당은 :
이#include <iostream>
#include <ThreadPool.h>
ThreadPool pool(3);
void fn() {
std::cout << std::this_thread::get_id() << '\n';
pool.enqueueTask(fn);
};
int main() {
std::cout << "Hello, World!" << std::endl;
pool.enqueueTask(fn);
return 0;
}
위 예제가 절대로 종료되지 않는다는 사실을 알고 있습니까? 작업은 항상 다른 작업을 시작합니다. – Steve
'threads' 맵은 결코 비어 있지 않습니까? 그리고 "function"에 대해 ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function)을 사용하지 않는 이유는 무엇입니까? –
@Steve 예, 더 오랜 기간 테스트하는 것입니다. – Wicpar