从usleep唤醒一个std :: thread [英] Wake up a std::thread from usleep

查看:191
本文介绍了从usleep唤醒一个std :: thread的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下示例:

#include <iostream>
#include <fstream>
#include <unistd.h>

#include <signal.h>
#include <thread>

void sleepy() {
    usleep(1.0E15);
}

int main() {
    std :: thread sleepy_thread(sleepy);

    // Wake it up somehow...?

    sleepy_thread.join();
}

在这里,我们有一个线程永远休眠.我想加入它,而不必永远等待它自发地从睡眠中醒来.有没有办法从外部告诉嘿,伙计!",以便我可以在合理的时间内加入它?

Here we have a thread that just sleeps forever. I want to join it, without having to wait forever for it to spontaneously wake from usleep. Is there a way to tell it from the extern "hey man, wake up!", so that I can join it in a reasonable amount of time?

我绝对不是线程专家,因此,如果可能,不要承担任何责任.

I am definitely not an expert on threads, so if possible don't assume anything.

推荐答案

其他答案是您可以使用定时静音来完成此操作.我整理了一个小类,使用定时互斥锁来阻止睡眠"线程,如果希望尽早唤醒"它们,则释放互斥锁.标准库为timed_mutex提供了一个名为try_lock_for的函数,该函数将尝试锁定互斥锁一段时间,然后再继续操作(并返回失败指示)

Other answers are saying you can use a timed muted to accomplish this. I've put together a small class using a timed mutex to block the 'sleeping' threads, and release the mutex if you want to 'wake' them early. The standard library provides a function for timed_mutex called try_lock_for which will try to lock a mutex for a period of time, before continuing on anyway (and returning an indication of failure)

可以将其封装在一个类中,例如以下实现,该类仅允许单个调用唤醒等待的线程.还可以通过包括一个waitUntil函数来等待,直到一个时间序列与timed_mutex的另一个定时等待函数try_lock_until相对应,来改进它,但是我将其留给有兴趣的人练习,因为它似乎一个简单的修改.

This can be encapsulated in a class, like the following implementation, which only allows a single call to wake waiting threads. It could also be improved by including a waitUntil function for waiting until a time series to correspond to the timed_mutex's other timed waiting function, try_lock_until but I will leave that as an exercise to the interested, since it seems a simple modification.

#include <iostream>
#include <mutex>
#include <thread>
#include <chrono>
#include <atomic>

// one use wakable sleeping class
class InterruptableSleeper{
    std::timed_mutex
        mut_;
    std::atomic_bool
        locked_; // track whether the mutex is locked
    void lock(){ // lock mutex
        mut_.lock();
        locked_ = true;
    }
    void unlock(){ // unlock mutex
        locked_ = false;
        mut_.unlock();
    }
public:
    // lock on creation
    InterruptableSleeper() {
        lock();
    }
    // unlock on destruction, if wake was never called
    ~InterruptableSleeper(){
        if(locked_){
            unlock();
        }
    }
    // called by any thread except the creator
    // waits until wake is called or the specified time passes
    template< class Rep, class Period >
    void sleepFor(const std::chrono::duration<Rep,Period>& timeout_duration){
        if(mut_.try_lock_for(timeout_duration)){
            // if successfully locked, 
            // remove the lock
            mut_.unlock();
        }
    }
    // unblock any waiting threads, handling a situation
    // where wake has already been called.
    // should only be called by the creating thread
    void wake(){
        if(locked_){
            unlock();
        }
    }
};


以下代码:


The following code:

void printTimeWaited(
  InterruptableSleeper& sleeper, 
  const std::chrono::milliseconds& duration){
    auto start = std::chrono::steady_clock::now();
    std::cout << "Started sleep...";
    sleeper.sleepFor(duration);
    auto end = std::chrono::steady_clock::now();
    std::cout 
        << "Ended sleep after "
        << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()
        << "ms.\n";
}

void compareTimes(unsigned int sleep, unsigned int waker){
    std::cout << "Begin test: sleep for " << sleep << "ms, wakeup at " << waker << "ms\n";
    InterruptableSleeper
        sleeper;
    std::thread
        sleepy(&printTimeWaited, std::ref(sleeper), std::chrono::milliseconds{sleep});
    std::this_thread::sleep_for(std::chrono::milliseconds{waker});
    sleeper.wake();
    sleepy.join();
    std::cout << "End test\n";
}

int main(){

    compareTimes(1000, 50);
    compareTimes(50, 1000);

}

打印

Begin test: sleep for 1000ms, wakeup at 50ms
Started sleep...Ended sleep after 50ms.
End test
Begin test: sleep for 50ms, wakeup at 1000ms
Started sleep...Ended sleep after 50ms.
End test

这篇关于从usleep唤醒一个std :: thread的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆