2013-07-13 6 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

неродственных красный флаг: Вы используете mutex 'm' для защиты' schedule_queue' в 'QueueSchedule', но не в' scheduler'. Чувство моих данных горит. – Casey

+0

Если 'schedule_queue' является однопроцессорной однопользовательской очередью, и вы используете мьютекс для синхронизации нескольких производителей, то мой смысл использования данных неверен и нуждается в исправлении. – Casey

ответ

0

Я не знаю, правильно ли я понял, что вы пытаетесь сделать, но если вы хотите общаться с определенным потоком из основного потока, вы можете просто установить флаг (объявленный как глобальную переменную) и сделать нитки справляются с этим флагом, чтобы изменить свое поведение по вашему желанию. Например, вы можете добавить эту переменную в оператор while, который продолжает выполнять вашу функцию scheduler(). Другая идея может включать использование condition variables.

Надеюсь, это поможет.

0

Посмотрите на Condition variables

Вместо «спать», резьбовые блоки на переменном состоянии, просыпаясь, когда он сигнализировал. Блокировка может быть тайм-аутом - так что, если конквар истечет, поток может сделать одну вещь (например, повторить цикл), и если сигнализация будет сигнализирована, она может сделать что-то еще.

Обратите внимание на предупреждения 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; 
} 

Скажите, если это помогает, о, если у вас есть какие-либо вопросы/замечания

Смежные вопросы