如果使用tbb::task::enqueue
在函數中排隊一個任務,然後在功能超出執行任務之前範圍,將任務迷路?線程構建模塊(TBB)```enqueue```任務壽命
如果是這樣,那怎麼可以避免?例如,如果你想在一個短暫的事件處理程序回調中加入一個任務,這個回調將很快超出範圍,而這個任務將不會被調度器執行,直到稍後呢?
此外,請問enqueue
功能有容量限制?如果有超過一定數量的待處理任務,它是否會放棄任務?
如果使用tbb::task::enqueue
在函數中排隊一個任務,然後在功能超出執行任務之前範圍,將任務迷路?線程構建模塊(TBB)```enqueue```任務壽命
如果是這樣,那怎麼可以避免?例如,如果你想在一個短暫的事件處理程序回調中加入一個任務,這個回調將很快超出範圍,而這個任務將不會被調度器執行,直到稍後呢?
此外,請問enqueue
功能有容量限制?如果有超過一定數量的待處理任務,它是否會放棄任務?
甲tbb::task
是一個對象。與其他C++對象相同,C++生命週期規則(和危險!)適用於tbb::task
。對於有問題的情況,確保以不受返回函數影響的方式捕獲任務中的信息。例如,捕獲本地變量的值,而不是引用。
這是一個使用lambda表達式顯示問題的程序。它借用Alexey Kukanov's lambda_task
#include <tbb/tbb.h>
template<typename F>
class lambda_task : public tbb::task {
F my_func;
/*override*/ tbb::task* execute() {
my_func();
return NULL;
}
public:
lambda_task(const F& f) : my_func(f) {}
};
template<typename F>
void tbb_enqueue_lambda(const F& f) {
tbb::task::enqueue(*new(tbb::task::allocate_root()) lambda_task<F>(f));
}
void LaunchOneTask(int i, int j) {
if(i%1000000==0)
[i,&j]{printf("Launching i=%d j=%d\n",i,j);}();
tbb_enqueue_lambda([i,&j]{ // Deliberate mistake for j!
printf("Hi from lambda: i=%d j=%d\n",i,j);
sleep(1);
});
}
int main() {
for(int i=0; i<1000000000; ++i) {
LaunchOneTask(i,i);
}
}
如果你運行它,你會看到「發射......」行打印i
和j
正確,但「喜從...」行打印錯誤值爲j
。這是因爲lambda已經通過引用(&j
)捕獲了j
,並且引用是在任務運行之前消失的左值。
據我所知,tbb::task::enqueue
容量極限是系統內存的容量限制。程序員要確保這不會發生。