Lambda中的指针引用

时间:2018-01-30 10:21:30

标签: c++ c++11 templates lambda

struct taskinfo
{
        long int id;
        bool cancel;
        std::function<void()> func;
        std::chrono::system_clock::time_point time;
        std::chrono::system_clock::duration interval;
        taskinfo(){ }

        bool operator<(const taskinfo& task) const {
            return time > task.time;
        }

        public:
        taskinfo(long int id, std::function<void()>&& f, const std::chrono::system_clock::time_point& t)
                : id(id), func(f),
                time(t)
        {
                cancel = false;
        }
}

....

std::priority_queue<taskinfo, std::vector<taskinfo>> tasks;
void at(taskinfo** task){
        std::function<void()> threadFunc = [task]() { std::thread((*task)->func).detach(); };
        (*task)->func = threadFunc;
        tasks.push(**task);
}

在main()..

std::vector<taskinfo*> requests;
for(int i=1; i <=5; i++ )
{
        taskinfo* t = new taskinfo(i, [i]{ timeoutFunc(i); }, std::chrono::system_clock::now() + std::chrono::milliseconds(timeout));
        tT.at(&t);
        requests.push_back(t);
        std::cout << "Request " << i << " Registered.... Time:" << std::chrono::system_clock::now().time_since_epoch().count() << std::endl;
}

我认为当我将该函数从队列中弹出来执行时,我在这里遗漏了一些东西,该函数可能为空,没有执行任何操作。

如果我将taskinfo复制到本地

void at(taskinfo** task){
            taskinfo t = **task;
            //Replace everything else with t function works fine But 
            //I need to modify the same reference
}

我如何在这里使用指针参考lambda?

我已经添加了我在这里尝试做的完整代码。

完整代码:

#include <functional>
#include <chrono>
#include <future>
#include <queue>
#include <thread>
#include <memory>
#include <sstream>
#include <assert.h>
#include <iostream>
#include <ctime>
#include <sys/time.h>
#include <unistd.h>
#include <limits.h>

#define TIMER_NO_TASK_SLEEP_TIME        100

struct taskinfo
{
        long int id;
        bool cancel;
        std::function<void()> func;
        std::chrono::system_clock::time_point time;
        std::chrono::system_clock::duration interval;

        taskinfo(){ }
        bool operator<(const taskinfo& task) const {
                return time > task.time;
        }

        public:
        taskinfo(long int id, std::function<void()>&& f, const std::chrono::system_clock::time_point& t)
                : id(id), func(f),
                time(t)
        {
                cancel = false;
        }
};

class TimerTask
{
        private:
                std::priority_queue<taskinfo, std::vector<taskinfo>> tasks;
                std::unique_ptr<std::thread> thread;
                bool keepRunning;

        public:
                TimerTask()
                        :keepRunning(true),
                        thread(new std::thread([this]() {
                                                while(keepRunning)
                                                {
                                                auto now = std::chrono::system_clock::now();
                                                while(!tasks.empty() && tasks.top().time <= now) {
                                                if(!tasks.top().cancel)
                                                {
                                                tasks.top().func();
                                                }
                                                tasks.pop();
                                                }

                                                if(tasks.empty()) {
                                                std::this_thread::sleep_for(std::chrono::milliseconds(TIMER_NO_TASK_SLEEP_TIME));
                                                } else {
                                                std::this_thread::sleep_for(tasks.top().time - std::chrono::system_clock::now());
                                                }
                                                }
                                                })){ }

                ~TimerTask()
                {
                        keepRunning = false;
                        thread->join();
                }

                //Execute a task when the timer times out
                void at(taskinfo** task){
                        std::function<void()> threadFunc = [task]() { std::thread((*task)->func).detach(); };
                        (*task)->func = threadFunc;
                        tasks.push(**task);
                }

                //Cancel the particular task with a flag
                void cancel(taskinfo** task){
                        (* task)->cancel = true;
                }
};

//The return type of the task must be void
void timeoutFunc(int id)
{
        std::cout << "Request " << id << " Timeout.... Executed Timeout Function Time:" << std::chrono::system_clock::now().time_since_epoch().count() << std::endl;
}

int main(int argc, char* argv[])
{
        if(argc != 2)
        {
                std::cout << "\n Usage <Process> <Timeout>" << std::endl;
                return 0;
        }

        int timeout = atoi(argv[1]);
        TimerTask tT;

        std::vector<taskinfo*> requests;
        requests.reserve(1000);
        for(int i=1; i <=5; i++ )
        {
                taskinfo* t = new taskinfo(i, [i]{ timeoutFunc(i); }, std::chrono::system_clock::now() + std::chrono::milliseconds(timeout));
                tT.at(&t);
                requests.push_back(t);
                std::cout << "Request " << i << " Registered.... Time:" << std::chrono::system_clock::now().time_since_epoch().count() << std::endl;
        }
        while(1) sleep(60);
        return 0;
}

1 个答案:

答案 0 :(得分:1)

您正在将指针传递给不再存在的指针:

taskinfo* t = new taskinfo(i, [i]{ timeoutFunc(i); }, std::chrono::system_clock::now() + std::chrono::milliseconds(timeout));
tT.at(&t);
requests.push_back(t);

在上面的代码中,t是为循环中的每次迭代实例化的局部变量。每次都会得到一个新的t

代码tT.at(&t);获取此临时地址。

修复程序位于呼叫网站呼叫:tT.at(t);。注意这就像requests.push_back(t);

此外:

//Execute a task when the timer times out
void TimerTask::at(taskinfo* task){
        std::function<void()> threadFunc = [task]() { std::thread(task->func).detach(); };
        task->func = threadFunc;
        ...
}