Имеется класс Worker:
class Worker : public AbstractWorker {
public:
Worker(Core* core, Module* module, WORKER_TYPE type = WORKER_TYPE::BEFORE_GRAPHICS, bool synchronized = false, const std::string& name = "");
Worker(std::function<void(Worker*, unsigned)> function, Core* core, Module* module, WORKER_TYPE type = WORKER_TYPE::BEFORE_GRAPHICS, bool synchronized = false, const std::string& name = "");
virtual ~Worker();
virtual void handle(unsigned microseconds);
WORKER_TYPE getType() const;
bool isSynchronized() const;
protected:
const WORKER_TYPE type;
const bool synchronized;
private:
std::function<void(Worker*, unsigned)> function;
};
Важным здесь является
std::function<void(Worker*, unsigned)> function;
, которая передаётся в конструкторе и вызывается из handle
void Worker::handle(unsigned microseconds)
{
if (function)
function(this, microseconds);
}
Сама функция handle вызывается из Core в цикле следующим образом:
while (_isAlive) {
// TODO: убрать расход ресурсов на выделение памяти и прочее
// parallel processing
std::vector<std::future<void>> tasks;
for (auto& worker : beforeGraphicsWorkers) {
beforeGraphicsWorkersThreadPool->enqueue(
[this, worker] {
auto now = getTimePoint();
auto dt = std::chrono::duration_cast<std::chrono::microseconds>(now - worker->previousHandlingTime).count();
worker->handle(dt);
worker->previousHandlingTime = now;
});
}
// wait for threads finishing
for (auto& task : tasks)
task.wait();
// остальный код
}
Если просто добавить лямбду, которая будет что-то делать, то всё ок, например так:
core.registerWorker(std::make_shared<Worker>([&core](auto worker, unsigned microseconds) {
static int i = 0;
i++;
}, &core, nullptr));
registerWorker добавляет Worker в vector, который перебирается в функции обработки, приведённой выше. Но если же в Worker добавить вывод, то память стремительно уходит в небытие, например так:
core.registerWorker(std::make_shared<Worker>([&core](auto worker, unsigned microseconds) {
static int i = 0;
i++;
std::cout << i << std::endl;
}, &core, nullptr));
Если наследоваться от Worker и не использовать лямбды, тоже самое.
Что за магия? Может это как-то связано с тем, что Worker'ы постоянно вызываются из разных потоков?
Valgrind говорит, что так и должно быть -_-
==5048==
==5048== HEAP SUMMARY:
==5048== in use at exit: 0 bytes in 0 blocks
==5048== total heap usage: 1,851,012 allocs, 1,851,012 frees, 85,222,489 bytes allocated
==5048==
==5048== All heap blocks were freed -- no leaks are possible
==5048==
==5048== For counts of detected and suppressed errors, rerun with: -v
==5048== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)