在运行前获取std :: thread的thread:id?

时间:2018-08-10 22:35:15

标签: c++ multithreading stdthread

我正在尝试在C ++ 11的std::thread之上构建一个线程安全层,其中每个对象都分配给一个拥有的线程,并且某些调用在错误的线程上使用时可能会引发严重错误。 。拥有线程是唯一可以将对象转移到另一个线程的线程。

我一切正常, 除外,我找不到在线程实际运行之前获取线程thread::id的方法。而且我需要在将新线程的ID附加到该对象之前,将其移交。

如果我使用

std::thread newThread( [theObject]()
                       {
                           // use theObject here.
                       } );

最早可以获取线程ID的地方是在定义线程对象之后,此时线程已经在运行。

我看到std::thread有一个默认的构造函数,但是我看不到给它一个以后在线程上运行的函数的方法。

是否可以在线程上执行两步构造,或者在创建时控制线程的ID?

4 个答案:

答案 0 :(得分:6)

您可以考虑让线程执行的功能在起飞前进行一些初始设置,而不是在开始运行之前获取线程的ID。例如,您可以执行以下操作:

bool isReady = false;
bool wasReceived = false;
std::mutex mutex;
std::condition_variable condition;

std::thread newThread([theObject, &isReady, &mutex, &condition] {
   /* Wait until we've been cleared to go. */
   std::unique_lock<std::mutex> lock(isReady);
   condition.wait(lock, [&isReady] { return isReady; });

   /* Signal that we're done. */
   wasReceived = true;
   lock.unlock();
   condition.notify_one();

   /* Put code here to do whatever it is that the thread should do. */
});

/* Read the thread's ID. It's currently waiting for us. */
auto id = newThread.get_id();

/* Tell the thread that we're ready for it. */
std::unique_lock<std::mutex> lock(mutex);
isReady = true;
condition.notify_one();

/* Wait until the thread has confirmed that it's ready. */
condition.wait(lock, [&] { return wasReceived; });

这将创建线程并将其放置并等待,直到创建者有机会读取其ID。一旦发生这种情况,创建者便会等待,直到线程确认已准备就绪,然后您就可以根据需要使用线程ID了。

当心上面代码中的错误-完全未经测试。 :-)

答案 1 :(得分:5)

否-创建线程后,它将立即开始运行。如果要在执行任何操作之前先获取其ID,则可能要创建一个小包装器,在该包装器中将线程(例如)传递给CV和一个队列,在该线程中存放输出。

然后,当线程启动时,它检索自己的ID,将其存储在输出队列中,然后等待CV。父母取回ID并准备好让孩子开始做某事时,它会向简历发出信号,然后就消失了。

答案 2 :(得分:3)

通过传递唯一的std :: promise参数来启动每个处于非活动状态的线程,首先获取线程ID(为此目的,线程ID用作通过引用参数传递的对象),然后让其等待线程设置诺言经理。这也将消除使用条件变量的麻烦。

已编辑代码段

class smart_thread {
public:
    smart_thread(std::function<void(void)> task)
    {
        thread_ = std::thread([=]() {
            id_ = std::this_thread::get_id();
            // wait here till activated
            future_.get();
            if(active_) task();
        });
    }

    void activate()  {
        promise_.set_value();
        active_ = true;
    }

    ~smart_thread() {
        if(!active_) promise_.set_value();
        thread_.join();
    }    
private:
    std::thread::id id_;
    std::atomic<bool> active_ = false;
    std::thread thread_;
    std::promise<void> promise_;
    std::future<void> future_ = promise_.get_future();
};

void main()
{
    auto task = []() { std::cout << "Hello World\n"; };
    smart_thread thread(task); // start thread inactive mode
    thread.activate(); // activate thread
}

答案 3 :(得分:0)

是否可以创建一个模板类,以Data,Class [ 0.02713807 0.01802697 0.01690036 0.01501216 0.01466412 0.01638859 0.0210163 0.02658022 0.03664452 0.05064286 0.06027664 0.06431134 0.04303673 0.03247764 0.02293602 0.01847688 0.0174582 0.01860664 0.02576164 0.02296149 0.0582211 0.37246149] ,[fail] [ 0.03623561 0.05211099 0.02469929 0.0134991 0.01029103 0.00880611 0.00898548 0.00870684 0.0117465 0.01962223 0.03895351 0.01956952 0.00972828 0.00704872 0.00656471 0.00689743 0.00854528 0.01128713 0.02119957 0.05047751 0.05028719 0.57473797] ,[fail] [ 0.04293871 0.0292026 0.02329546 0.01473342 0.01127858 0.0107691 0.01203 0.01478981 0.02045828 0.03043333 0.03817313 0.03602836 0.02284631 0.014719 0.00999932 0.00857384 0.00940592 0.0143105 0.02862624 0.03424553 0.05910089 0.51404167] ,[pass] [ 0.0274558 0.02260355 0.0120938 0.00766592 0.00623965 0.00700311 0.0105109 0.01435633 0.0228327 0.03671535 0.0509835 0.06406992 0.03382424 0.02283531 0.01455474 0.01196762 0.01238184 0.01560769 0.02885654 0.03067498 0.07337675 0.47338975] ,[pass] [ 0.04557506 0.03065541 0.02441537 0.0145579 0.0114853 0.01115224 0.01330945 0.01539609 0.01776064 0.0216626 0.02218757 0.02153467 0.01548431 0.01295433 0.01045522 0.0100229 0.01051257 0.01454908 0.02735121 0.03250603 0.05923302 0.55723903] ,[pass] 的形式接受线程例程。如果需要传递其他参数,则可以使用匿名闭包轻松完成此操作。

std::function<void(T *object)>

当心上面代码中的错误-完全未经测试。 :-):-)