2016-10-29 2 views
2

Я тренируюсь с потоками и параллелизмом потоков, и я хочу создать свой собственный пул потоков. Для этого у меня есть вектор потоков, эти потоки будут ждать переменной условия, чтобы получить следующую функцию для выполнения из другого вектора.C++ pass function to thread pool

Но у меня есть проблемы с хранением/передачей/выполнением функций с неизвестными аргументами. Может кто-нибудь, пожалуйста, дайте мне подсказку, как это сделать или что мне нужно для этого?

работает EDIT:

Добавление задачи: петля

ThreadPool tp(10); 
tp.execute(std::bind(print, i)); 

void print(int i) { 
    std::cout << i << std::endl; 
} 

void ThreadPool::execute(const std::function<void()> function) { 
    l.lock(); 
    if (running) { 
     queue.push_back(function); 
     cv.notify_one(); 
    } else { 
     // TODO error 
     std::cout << "err execute()\n";  
    } 
    l.unlock(); 
} 

Тема:

// set up threads in constructor 
for (int i = 0; i < size; i++) { 
    threads.push_back(std::thread(&ThreadPool::thread_loop, std::ref(*this), i)); 
} 

static void ThreadPool::thread_loop(ThreadPool &pool, int id) { 
    pool.o.lock(); 
    std::cout << "pool-" << pool.id << "-thread-" << id << " started\n"; 
    pool.o.unlock(); 
    std::function<void()> function; 
    std::unique_lock<std::mutex> ul(pool.m, std::defer_lock); 

    while (pool.running || pool.queue.size() > 0) { 
     ul.lock(); 
     while (pool.queue.size() == 0) { 
      pool.cv.wait(ul); 
     } 
     pool.l.lock(); 
     if (pool.queue.size() == 0) { 
      pool.l.unlock(); 
      continue; 
     } 
     function = pool.queue.at(0); 
     pool.queue.erase(pool.queue.begin()); 
     pool.l.unlock(); 
     ul.unlock(); 
     function(); 
    } 
} 
+0

Напрашивается из 'станд :: функции '. При этом вы можете передать любой аргумент 0-аргумента, который вы хотите (функция, объект функции, лямбда, результат 'std :: bind', вы назовите его) в ваш threadpool, и он будет работать. –

+0

Вы можете сделать m_threads.push_back (std :: thread (& InitThreadsFoo, m_threads.size())); но я тоже хотел бы знать, как переназначить существующий поток из вектора, чтобы взять на себя другую функцию, или назначить функцию уже существующему потоку, который уже использовался. – ReturnVoid

+0

@ Андрей Туркин благодарю вас, это отлично работает! – Pali

ответ

0

Вам нужно добавить функцию + аргументы как VARIADIC шаблона:

template<class Task, class ...Args> 
void ThreadPool::execute(Task&& task, Args&& ... args) { 
    l.lock(); 
    if (running) { 
     queue.emplace_back(std::bind(std::forward<Task>(task),std::forward<Args>(args)...)); 
     cv.notify_one(); 
    } else { 
     // TODO error 
     std::cout << "err execute()\n";  
    } 
    l.unlock(); 
} 

Пример использования:

ThreadPool tp(/*whatever you pass the thread pool constructor*/); 
tp.execute(printf,"hello from the threadpool.");