代码之家  ›  专栏  ›  技术社区  ›  PiotrK

如何在C++中尽可能自动地用命名标记标记每个线程?

  •  0
  • PiotrK  · 技术社区  · 7 年前

    我需要考虑我们将要开发的C++/17'应用程序中的所有线程;

    线程帐户本身是 thread_local

    问题是 本地线程 Can I have thread_local object which ctor/dtor will be called on each thread creation even if it is not used? )。之后,它将在线程退出时正确销毁。

    我最初的想法是这样做:

    thread_local thread_accounter_t thread_accounter; // This is main accounter object
    
    void thread_started(std::string name, std::string function, std::string filename, int line)
    {
       thread_accounter.thread_started(name, function, filename, line);
    }
    #define THREAD_STARTED(name) thread_started(name, __FUNCTION__, __FILE__, __LINE__)
    

    然后,在每个线程中使用:

    std::thread my_thread([](){
        THREAD_STARTED("example");
        // Do actual job
    });
    

    这种方法有一个非常严重的缺点:它容易出错。每个不使用宏的线程(即由于忽略)对accounter都是不可见的。

    我的下一个想法是继承遗产 std::thread our::thread 它们将被强制(由构造函数)填充线程名。通过使用简单的技巧,我们可以强制用户不使用 螺纹 .

    class thread : public std::thread
    {
       public:
           thread_t() noexcept {}
           thread_t( thread_t&& other ) noexcept : std::thread(std::move(other)) {}
           template<class function_t, class... args_t >
    
    // Following constructor actually does not compile:
           explicit thread_t(std::string name, std::string function, std::string filename, int line, function_t&& f, args_t&&... args ) :
           std::thread(std::bind([name, function, filename, line](function_t&& f, auto&&... args){
               thread_started(name, function, filename, line);
               f(std::forward(args)...);
           }, std::move(f), std::move(args)...)) { }
           thread_t(const thread_t&) = delete;
    };
    #define THREAD_NAME(name) name, __FUNCTION__, __FILE__, __LINE__
    

    那就用它吧:

    thread my_thread(THREAD_NAME("sample thread"), [](){
        // Do actual job
    });
    

    问题有两个方面:

    thread 那么它会编译吗? https://pastebin.com/mNMpunMT

    2.)如果我的方法可以纠正,那么什么是更好的方法?

    1 回复  |  直到 7 年前
        1
  •  0
  •   PiotrK    7 年前

    搞定了!

    这个 std::bind std::thread 构造函数可以接受任意参数。这是最终版本:

    #include <iostream>
    #include <thread>
    
    void thread_started(std::string name, std::string function, std::string filename, int line)
    {
    
    }
    
    class thread_t : public std::thread
    {
       public:
           thread_t() noexcept {}
           thread_t( thread_t&& other ) noexcept : std::thread(static_cast<std::thread&&>(std::move(other))) {}
           template<class function_t, class... args_t >
    
           explicit thread_t(std::string name, std::string function, std::string filename, int line, function_t&& f, args_t&&... args ) :
           std::thread([name, function, filename, line](function_t&& f, auto&&... args){
               thread_started(name, function, filename, line);
               f(std::move(args)...);
           }, std::move(f), std::move(args)...) { }
           thread_t(const thread_t&) = delete;
    };
    #define THREAD_NAME(name) name, __FUNCTION__, __FILE__, __LINE__
    
    int main()
    {
        thread_t my_thread(THREAD_NAME("sample thread"), [](){
            // Do actual job
           std::cout << "Hello!";
        });
        std::cout << "Hello, world!\n";
    }