2013-07-15 4 views
1

У меня есть простая реализация пула потоков с использованием boost::function и boost::bind, чтобы уменьшить подпись функции-члена до void func(void). Затем он использует очередь boost::function и int пар, выдает верхнюю часть очереди и выполняет эту функцию (все они завернуты в блок мьютекса).Boost :: функция связанная функция члена становится недействительной

threadPool->addJob(boost::bind(&Foo::bar, this, arg1, arg2)); 

... 

typedef boost::function<void(void)> func; 
std::queue<std::pair<func, int> > funcQ; 

void ThreadPool::addJob(func f){ 
    funcQ.push(std::make_pair(f, j)); 
} 

if (!funcQ.empty()){ 
    func localFunc = (funcQ.front()).first; 
    ... 
    funcQ.pop(); 
    ... 
    localFunc(); 
} 

Однако после нескольких итераций, это вызывает Segfault, когда я ссылался на () оператора на функцию, так что я бросил в заявлении утверждают, чтобы убедиться, что функция была вызываемая:

... 
assert(funcQ.front().first); 
func localFunc = (funcQ.front()).first; 
... 

И вот, после нескольких итераций утвердительные поездки, указывая, что мой boost::function не был вызван.

Сначала я подумал, что, возможно, данные функции (из класса Foo) были уничтожены до того, как функция была вызвана, однако, как я понимаю, boost::function создает копию данных, чтобы сформировать закрытие. К сожалению, я недостаточно знаю о причинах, по которым boost::function s недействителен для дальнейшего продвижения по этой проблеме. Я привязываю функцию-член неправильно, или проблема лежит где-то между ними и пытается ее называть?

Редактировать: Я должен был упомянуть: Foo распределяется по куче и не равен delete d до тех пор, пока нити не будут объединены.

+2

'boost :: function' создаст копию указателя' this', который вы передадите, т. Е. Сохранит указатель с тем же адресом. У него нет копии '* this'. – juanchopanza

ответ

1

std :: queue is not thread safe. Когда вы говорите, что используете mutex для выхода из очереди, я понимаю, что вы будете делать то же самое, что и в очереди.

Кроме того, вам необходимо позаботиться о жизни Foo. Рассмотрим передачу shared_ptr на асинхронные функции. (shared_from_this() вместо этого)

Примечание: вы можете использовать boost :: asio для выполнения планирования задач. Вот очень хорошая статья об этом http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio/

+0

Я действительно обертываю каждый раз, когда очередь обращается в мьютексе. Foo выделяется в куче, а деструктор не вызывается до тех пор, пока потоки не будут соединены. Кроме того, я сделал это, чтобы попытаться понять, как использовать boost :: function и boost :: bind, но я обязательно посмотрю на boost :: asio, спасибо! – Oxonium