2016-12-19 3 views
2

Я изучаю C++ со вчерашнего дня, и я хотел бы закодировать систему сигнализации, которая позволяет пользователю устанавливать свои собственные сигналы тревоги с объектом Alarm. Я пытаюсь работать сам по себе, но только позволяет пользователю запустить его: если я попытаюсь использовать метод start для запуска второго аварийного сигнала, программа ожидает, что первый сигнал «звонит», чтобы запустить второй.Выполнять объекты одного и того же класса одновременно

Как я могу запустить два будильника одновременно? Спасибо, что нашли время, читая это. (OSX Sierra, Xcode 8,2)

main.cpp

using namespace std; 

int main(int argc, const char * argv[]) { 
    Alarm test(12, 12, "foo"); 
    test.start(); 

Alarm.hpp

class Alarm { 
    public: 
    Alarm(int hour, int minute, std::string speech); 
    void start(); 
    void stop(); 
    bool isStopped() const; 
    std::string getStats() const; 

    private: 
    int m_hour; 
    int m_minute; 
    std::string m_speech; 
    bool m_stopped; 
}; 

Alarm.cpp

using namespace std; 

Alarm::Alarm(int hour, int minute, string speech) { 
    m_hour = hour; 
    m_minute = minute; 
    m_speech = speech; 
    m_stopped = false; 
} 

void Alarm::start() { 
    int currentHour, currentMinute; 

    while (!Alarm::isStopped()) { 
     time_t now = time(NULL); 
     struct tm *current = localtime(&now); 

     currentHour = current->tm_hour; 
     currentMinute = current->tm_min; 

     if (currentHour == m_hour && currentMinute == m_minute) { 
      cout << m_speech << endl; 
      m_stopped = true; 
     } 
     else { 
      this_thread::sleep_for(chrono::milliseconds(60000)); 
     } 
    } 
}  

void Alarm::stop() { 
    m_stopped = true; 
} 

bool Alarm::isStopped() const { 
    return m_stopped; 
} 
+7

Похоже, вам нужно узнать многопоточность. – NathanOliver

+2

Вместо случайных «обучающих программ» в Интернете ** изучайте язык из книги **. –

+0

Вот список некоторых [C++ книг] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). –

ответ

2

Самый простой способ я мог придумать что-то, как с помощью std::thread S:

int main(int argc, const char * argv[]) {   
    Alarm test1(12, 12, "foo"); 
    Alarm test2(12, 12, "foo"); 

    std::thread t1(&Alarm::start,test1); 
    std::thread t2(&Alarm::start,test2); 

    while(!test1.isStopped() && !test2.isStopped()) { 
     this_thread::sleep_for(chrono::milliseconds(60000)); 
    } 

    t2.join(); 
    t1.join(); 
} 

и защиты переменной m_stopped члена с std::mutex, std::atomic или аналогичные:

class Alarm { 
    public: 
    Alarm(int hour, int minute, std::string speech); 
    Alarm(const Alarm& other); 
    Alarm& operator=(const Alarm& other); 
    void start(); 
    void stop(); 
    bool isStopped() const; 
// std::string getStats() const; 

    private: 
    int m_hour; 
    int m_minute; 
    std::string m_speech; 
    std::atomic<bool> m_stopped; 
}; 

Alarm::Alarm(int hour, int minute, string speech) 
: m_hour(hour),m_minute(minute),m_speech(speech),m_stopped(false) { 
} 

Alarm::Alarm(const Alarm& other) 
: m_hour(other.m_hour),m_minute(other.m_minute),m_speech(other.m_speech),m_stopped(other.isStopped()) { 
} 

Alarm& Alarm::operator=(const Alarm& other) { 
    m_hour = other.m_hour; 
    m_minute = other.m_minute; 
    m_speech = other.m_speech; 
    m_stopped.store(other.isStopped()); 
    return *this; 
} 

void Alarm::start() { 
    int currentHour, currentMinute; 

    while (!Alarm::isStopped()) { 
     time_t now = time(NULL); 
     struct tm *current = localtime(&now); 

     currentHour = current->tm_hour; 
     currentMinute = current->tm_min; 

     if (currentHour == m_hour && currentMinute == m_minute) { 
      cout << m_speech << endl; 
      m_stopped.store(true); 
     } 
     else { 
      this_thread::sleep_for(chrono::milliseconds(1000)); 
     } 
    } 
}  


void Alarm::stop() { 
    m_stopped.store(true); 
} 

bool Alarm::isStopped() const { 
    return m_stopped.load(); 
} 

Обратите внимание на изменения, которые я сделал в приведенном выше примере относительно конструктора копирования и определения оператора присваивания для правильной обработки элемента std::atomic<bool>.


У меня есть компилируемая версия here, с правильными параметрами она должна добиться успеха и своевременно завершить.

+0

Я получаю «вызов нестатической функции-члена без аргумента объекта» с этим кодом при попытке запустить потоки ... – sohomangue

+0

@sohomangue Извините, я всегда сбиваю с толку заказ (вот почему я ставлю это предупреждение). –

+0

@sohomangue У меня есть компилируемая версия, посмотрите. TLE из-за параметризайтона. –

0

Вам нужно многопоточность для этого, но для вашего случая я рекомендую проверить один вариант после другого.

0

Стандартный способ обработки нескольких аварийных сигналов - это поиск по всем тревогам, чтобы найти тот, который собирается «позвонить» первым и поспать достаточно долго для этого. Когда он выстрелил, удалите его из списка и найдите следующий, который будет звонить первым. (Поиск первого аварийного сигнала проще, если вы храните тревоги в сортированном контейнере, таком как std::map<time_t, Alarm> или даже просто std::map<time_t, std::string>)

Не забывайте обращаться с случаями, когда одновременно срабатывает несколько аварийных сигналов.

Если вы хотите, чтобы пользователь имел возможность взаимодействовать с системой во время ее работы (например, добавление новых аварийных сигналов, удаление аварийных сигналов и т. Д.), Вам все равно потребуется многопоточность - но вы должны иметь только один поток, спящий для следующий сигнал тревоги, а не один поток для каждого аварийного сигнала.

+0

На самом деле я закодировал эту систему в Python, и каждый сигнал тревоги запустил поток, и я подумал о том, чтобы делать то же самое в C++ ... Но я действительно не знаю, как это сделать. Даже если это слишком много, как я могу запустить поток через метод объекта? – sohomangue

+0

Если я не могу сделать иначе, я попробую этот метод, хотя – sohomangue

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