2013-07-13 88 views
0

背景

我目前正在開發一個使用C++ 11的覆盆子pi程序。基本設計(與這個問題有關)是:強制線程在睡覺時返回

  • 我有一個主循環等待來自外部源的命令。
  • 在主循環中,我創建了一個代理(在單獨的線程中運行的對象),該代理休眠直到將某些內容添加到其隊列中,在這種情況下,它會喚醒,處理此項目,然後檢查是否有任何項目然後回到睡眠再次隊列(該過程重複,如果有更多的處理)

在該項目的「處理」,我只使能/禁止的GPIO引腳一次一個的秒X量。

處理的僞代碼:

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%將要花費睡着(它執行代碼的唯一時間是當它的設置引腳輸出(沒有數據在這裏感動)

問題

我應該如何去從主線程取消當前項的處理?我不想殺死線程,永遠,我只是希望它回到它的運行循環來處理隊列中的下一個項目(或返回到睡眠狀態)。

我可以想辦法做到這一點,我只想聽到社區的幾個想法,並選擇最佳的解決方案。

附加代碼

這是在單獨的線程中運行類做隊列中的項目的處理。 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()); 
    } 
} 

預先感謝任何幫助。

+0

無關紅旗:您正在使用互斥鎖'm'來保護'QueueSchedule'中的'schedule_queue',但不保存'scheduler'中。我的數據競賽意識刺痛。 – Casey

+0

如果'schedule_queue'是單生產者單消費者隊列,並且您正在使用互斥鎖來同步多個生產者,那麼我的數據競爭感是錯誤的,需要修復。 – Casey

回答

0

我不知道我是否理解你正在嘗試做什麼,但是如果你想與主線程中的某個線程進行通信,你可以簡單地設置一個標誌(聲明爲全局變量)並使線程會查詢此標誌以便根據需要更改其行爲。例如,您可以將此變量添加到繼續執行scheduler()函數的while語句中。其他想法可能涉及使用condition variables

希望它有幫助。

0

查找到Condition variables

而是「沉睡」,對條件變量的線程塊,中醒來時,它的信號。阻塞可以是超時 - 所以如果condvar超時,線程可以做一件事(例如再次繞過循環),並且如果condvar被髮送信號,它可以做其他事情。

請注意wait_for有關虛假喚醒的警告。

僞上下的代碼可能是:

// 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); 

還是我誤解你以後在做什麼?

0

嗨我有一個例子,可以幫助你理解條件變量的工作方式。 你聲明瞭兩個線程(兩個無限循環)。

  • 即需要一個輸入準備處理
  • 另一種是對其進行處理,並通知他做

下面是代碼

用戶輸入信號給其他線程
#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; 
} 

告訴我,有沒有什麼幫助,o如果您有任何疑問/附註