首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跟踪用于调试的线程创建点

跟踪用于调试的线程创建点
EN

Stack Overflow用户
提问于 2013-06-03 09:35:46
回答 1查看 252关注 0票数 7

我开始喜欢lambdas了,不久前我写了一个简单的包装器,它使用lambda并在一个新线程上启动它。

代码语言:javascript
复制
//
// Starts a task on a separate thread, when passed a lambda expression
//
template<typename T>
smart_ptrs::w32handle StartTask(T f)
{
    // Make a copy of the task on the heap
    T* pTask = new T(f);

    // Create a new thread to service the task
    smart_ptrs::w32handle hThread(::CreateThread(
        NULL, 
        0, 
        (LPTHREAD_START_ROUTINE)& detail::start_task_proc<T>, 
        (LPVOID) pTask, 
        NULL, 
        NULL)); 

    // If the caller ignores this rc, the thread handle will simply close and the
    // thread will continue in fire-and-forget fashion.
    return hThread;
}

注意到:是的,我知道这并不需要模板,可以很高兴地使用std::function。我以这种方式发布它,因为它匹配更复杂的(异步队列)版本,这些版本必须是模板。

最终的结果是一个非常容易在并行算法中使用的函数。但是,如果你开始广泛地使用这样一个函数,就会出现一个问题。因为创建的线程似乎都来自同一个相当通用的函数,所以很难分辨它们在代码中的启动位置。通常可以从他们正在做的事情的上下文中得出结果,但在使用显式线程函数时,这并不像以前那么容易。有没有人有一个很好的方法来标记这样的线程,这样它们就更容易调试了?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-03 10:41:12

据我从代码中可以看出,在它们的调用堆栈中有一个start_task_proc的线程调用它们的函数对象。您可以修改该函数以获取指向“任务信息”结构的指针,而不是裸函数对象。您可以将任何您喜欢的信息填充到该信息对象中,例如创建任务的位置的行号和文件名:

代码语言:javascript
复制
template <class T>
struct TaksInfo {
  T func;
  unsigned line;
  char const* file;

  TaskInfo(T&& t, unsigned l, char const* f)
    : func(std::move(t), line(l), file(f) {}
};


template<typename T>
smart_ptrs::w32handle StartTask(T f, unsigned line, char const* file)
{
    // Make a copy of the task on the heap
    auto pTask = new TaskInfo<T>(f, line, file);

    // Create a new thread to service the task
    smart_ptrs::w32handle hThread(::CreateThread(
        NULL, 
        0, 
        (LPTHREAD_START_ROUTINE)& detail::start_task_proc<T>, 
        (LPVOID) pTask, 
        NULL, 
        NULL)); 

    // If the caller ignores this rc, the thread handle will simply close and the
    // thread will continue in fire-and-forget fashion.
    return hThread;
}

#define START_TASK(f) StartTask(f, __LINE__, __FILE__)

template <class T>
DWORD start_task_proc(LPVOID lpParameter) {
  auto pTask = (TaskInfo<T>*) lpParameter;
  return pTask->func();
}


//use:
int main() {
  auto threadHandle = START_TASK(([]() -> DWORD { std::cout << "foo\n"; return 42;} ));
}

如果现在检查pTask中的start_task_proc,您可以看到fileline可以告诉您任务是在哪里启动的。

当然,您可以避免使用TaskInfo结构,并将信息作为start_task_proc的模板参数。

代码语言:javascript
复制
template <class T, unsigned Line, char const* File>
DWORD start_task_proc(LPVOID lpParameter) { /* as you have it */)

template<unsigned Line, char const* File, typename T> //use T last fur type deduction
smart_ptrs::w32handle StartTask(T f)
{
    // Make a copy of the task on the heap
    auto pTask = new T(std::move(f));

    // Create a new thread to service the task
    smart_ptrs::w32handle hThread(::CreateThread(
        NULL, 
        0, 
        (LPTHREAD_START_ROUTINE)& detail::start_task_proc<T, Line, File>,   //!!!
        (LPVOID) pTask, 
        NULL, 
        NULL)); 

    // If the caller ignores this rc, the thread handle will simply close and the
    // thread will continue in fire-and-forget fashion.
    return hThread;
}

#define START_TASK(f) StartTask<__LINE__, __FILE__>(f)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16893777

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档