同时运行同一类的对象

时间:2016-12-19 18:58:24

标签: c++ xcode macos

我从昨天开始学习C ++,并且我想编写一个警报系统,让用户使用Alarm对象设置自己的警报。 我尝试的方法本身就可以工作,但只允许用户运行一个:如果我尝试使用start方法启动第二个警报,程序会等待第一个警报响起" ring"开始第二个。

如何同时运行两个闹钟? 感谢您花时间阅读本文。 (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;
}

3 个答案:

答案 0 :(得分: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();
}

并使用std::mutexstd::atomic或类似内容保护m_stopped成员变量:

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,其正确的参数应该会成功并及时完成。

答案 1 :(得分:0)

你需要多线程才能做到这一点,但是对于你的情况,我建议你先检查一个对象。

答案 2 :(得分:0)

可以在自己的线程中运行每个警报,但对于刚刚启动C ++的人来说这可能有点先进 - 而且无论如何它都有点过分。

处理多个警报的标准方法是搜索所有警报,找到即将发出警报的警报。首先,睡觉时间足够长。当它触发时,将其从列表中删除并搜索下一个将首先响铃的那个。 (如果将警报保存在已排序的容器中,例如std::map<time_t, Alarm>或甚至只是std::map<time_t, std::string>),查找第一个警报会更容易

请记住在需要同时触发多个警报时处理案件。

如果您希望用户能够在系统运行时与系统进行交互(例如添加新警报,删除警报等),您仍然需要多线程 - 但您应该只有一个线程正在休眠下一个警报,而不是每个警报一个线程。