Multithreading 强制线程在睡眠时返回 背景

Multithreading 强制线程在睡眠时返回 背景,multithreading,c++11,sleep,kill,Multithreading,C++11,Sleep,Kill,我目前正在使用C++11为raspberry pi开发一个程序。基本设计(与此问题相关)为: 我有一个主循环,它正在等待来自外部源的命令 在主循环中,我创建了一个代理(在单独线程中运行的对象),该代理将一直休眠,直到有东西添加到其队列中,在这种情况下,它将唤醒并处理该项,然后在返回休眠之前再次检查队列中是否有任何项(如果有更多项要处理,则重复此过程) 在项目的“处理”过程中,我只是在X秒内一次启用/禁用一个GPIO引脚 处理伪代码: for (Pin pin : pins) { se

我目前正在使用C++11为raspberry pi开发一个程序。基本设计(与此问题相关)为:

  • 我有一个主循环,它正在等待来自外部源的命令
  • 在主循环中,我创建了一个代理(在单独线程中运行的对象),该代理将一直休眠,直到有东西添加到其队列中,在这种情况下,它将唤醒并处理该项,然后在返回休眠之前再次检查队列中是否有任何项(如果有更多项要处理,则重复此过程)
在项目的“处理”过程中,我只是在X秒内一次启用/禁用一个GPIO引脚

处理伪代码:

for (Pin pin : pins)
{
    set_pin(pin, HIGH);
    this_thread::sleep_for(chrono::seconds(x))
    set_pin(pin, LOW);
    this_thread::sleep_for(chrono::seconds(y))
}
显然,该线程99.999%的时间将用于睡眠(它执行代码的唯一时间是在设置pin输出时(此处不涉及数据)

问题: 我应该如何从主线程取消当前项目的处理?我不想终止线程,我只是希望它返回到它的运行循环来处理队列中的下一个项目(或返回睡眠)

我可以想办法做到这一点,我只是想听听社区的一些想法,并选择最好的解决方案

附加代码 这个类在单独的线程中运行,处理队列中的项目。
schedule->RunSchedule(schedule)
是对上述伪代码描述的函数的调用

ScheduleThread.cpp

#include "ScheduleThread.h"

ScheduleThread::ScheduleThread()
    : thread(&ScheduleThread::run, this)
{
}

ScheduleThread::~ScheduleThread() {
    // TODO Auto-generated destructor stub
}

void ScheduleThread::QueueSchedule(Schedule *schedule)
{
    lock_guard<mutex> lock(m);
    schedule_queue.push(schedule);
    stateChangedSema.post();
}

bool ScheduleThread::scheduler()
{
    if (!schedule_queue.empty())
    {
        Schedule *schedule = schedule_queue.front();
        schedule->RunSchedule();
        schedule_queue.pop();
        return true;
    }
    return false;
}

void ScheduleThread::run()
{
    for(;;)
    {
        stateChangedSema.wait();
        while (scheduler());
    }
}
#包括“ScheduleThread.h”
ScheduleThread::ScheduleThread()
:thread(&ScheduleThread::run,this)
{
}
ScheduleThread::~ScheduleThread(){
//TODO自动生成的析构函数存根
}
void ScheduleThread::QueueSchedule(Schedule*Schedule)
{
锁和防护锁(m);
调度队列推送(调度);
stateChangedSema.post();
}
bool ScheduleThread::scheduler()
{
如果(!schedule_queue.empty())
{
Schedule*Schedule=Schedule_queue.front();
计划->运行计划();
schedule_queue.pop();
返回true;
}
返回false;
}
void ScheduleThread::run()
{
对于(;;)
{
stateChangedSema.wait();
while(scheduler());
}
}

提前感谢您的帮助。

我不知道我是否理解您的意图,但是如果您想从主线程与某个线程通信,您只需设置一个标志(声明为全局变量)并使线程参考此标志,以便根据需要更改其行为。例如,您可以将此变量添加到保持执行
调度程序()
函数的
while
语句中。其他想法可能涉及使用

希望有帮助。

调查

线程不会“休眠”,而是阻塞条件变量,并在发出信号时唤醒。阻塞可能是一个超时-因此,如果condvar超时,线程可以做一件事(例如,再次循环),如果condvar发出信号,它可以做其他事情

注意关于虚假醒来的警告

伪ish代码可能是:

// assumes the condvar is triggered when cancellation is reqd.

if(condvar.wait_for( lock, std::chrono::seconds( x ) ) != std::cv_status::timeout)
    return;
set_pin(pin, HIGH);
if(condvar.wait_for( lock, std::chrono::seconds( y ) ) != std::cv_status::timeout)
    return;
set_pin(pin, LOW);

还是我误解了你的意思?

嗨,我有一个例子可以帮助你理解条件变量是如何工作的。 您可以声明两个线程(两个无限循环)

  • 一个接收用户输入并向另一个线程发出信号,表明一个输入已准备好进行处理的线程
  • 另一个处理它并发出信号说他已经完成了
这是密码

#include <thread>
#include <chrono>
#include <mutex>
#include <iostream>
#include <string>
#include <condition_variable>
#include <atomic>
using namespace std;

//this simulates any action from the user (use it for your pin for example)
int GetUserName()
{
    while (true)
    {
        cout<<"Enter your name " << endl;
        cin>> UserName;
        NewName=true;//one new name is ready to be processed
        cv.notify_one();

        // Wait until the naame has been processed
        {
            std::unique_lock<std::mutex> lk(m);
            cv.wait(lk, []{return (NewName==false);});
        }   
    }
    return 0;
}

//this reacts to any action of the user, processes the data and signals that he's done
int ProcessName()
{
    while (true)
    {
            //waiting for one data to be processed
        {
            std::unique_lock<std::mutex> lk(m);
            cv.wait(lk, []{return (NewName==true);});
        }
        cout<<"Hey "+UserName<<"!"<<endl;
        NewName=false;//sets to flase because the data are processed
        cv.notify_one();//I have processed the data, the user can input something else
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
//这将模拟用户的任何操作(例如,将其用于pin)
int GetUserName()
{
while(true)
{

coutUnrelated red flag:您在
QueueSchedule
中使用mutex
m
来保护
schedule\u queue
,但在
scheduler
中没有。我的数据竞争感觉很刺痛。如果
schedule\u queue
是单生产者单消费者队列,并且您正在使用mutex来同步多个生产者,那么我的数据竞争-sense是错误的,需要修复。