0

さまざまな時間間隔でタスクをスケジュールしたい:0.1秒、0.9秒.... 2秒などシミュレーションの開始以降のティック数を返すclock()C ++関数を使用し、ティック数を次のように変換します。 CLOCKS_PER_SECを使用して秒数ですが、インスタントが浮動小数点数の場合はタスクがスケジュールされていないことに気付きましたが、整数の場合はスケジュールされています。ここに、スケジューリングを担当するコードの部分があります。

float goal = (float) clock() / CLOCKS_PER_SEC + 0.4 ;  // initially (float) clock() / CLOCKS_PER_SEC = 0 ; 
if ((float) clock() / CLOCKS_PER_SEC == goal) 
     do stuff ; 

その場合は機能しませんが、たとえばタスクを3秒で実行するようにスケジュールすると機能します。精度の問題ですか?

4

3 に答える 3

14

C ++でタイマーメカニズムを実装する場合は、おそらくstd::chrono名前空間をと一緒に使用しますstd::priority_queue

#include <functional>
#include <queue>
#include <chrono>
#include <sys/time.h>  // for `time_t` and `struct timeval`

namespace events
{
    struct event
    {
        typedef std::function<void()> callback_type;
        typedef std::chrono::time_point<std::chrono::system_clock> time_type;

        event(const callback_type &cb, const time_type &when)
            : callback_(cb), when_(when)
            { }

        void operator()() const
            { callback_(); }

        callback_type callback_;
        time_type     when_;
    };

    struct event_less : public std::less<event>
    {
        bool operator()(const event &e1, const event &e2) const
        {
            return (e2.when_ < e1.when_);
        }
    };

    std::priority_queue<event, std::vector<event>, event_less> event_queue;

    void add(const event::callback_type &cb, const time_t &when)
    {
        auto real_when = std::chrono::system_clock::from_time_t(when);

        event_queue.emplace(cb, real_when);
    }

    void add(const event::callback_type &cb, const timeval &when)
    {
        auto real_when = std::chrono::system_clock::from_time_t(when.tv_sec) +
                         std::chrono::microseconds(when.tv_usec);

        event_queue.emplace(cb, real_when);
    }

    void add(const event::callback_type &cb,
             const std::chrono::time_point<std::chrono::system_clock> &when)
    {
        event_queue.emplace(cb, when);
    }

    void timer()
    {
        event::time_type now = std::chrono::system_clock::now();

        while (!event_queue.empty() &&
               (event_queue.top().when_ < now))
        {
            event_queue.top()();
            event_queue.pop();
        }
    }
}

使用するには、を使用してイベントを追加し、毎秒数回events::add呼び出します。events::timer

簡単な

void foo()
{
    std::cout << "hello from foo\n";
}

void done()
{
    std::cout << "Done!\n";
}

struct bar
{
    void hello()
    {
        std::cout << "Hello from bar::hello\n";
    }
};

auto now = std::chrono::system_clock::now();
bar b;

events::add(foo, now + std::chrono::seconds(2));

events::add(std::bind(&bar::hello, b), now + std::chrono::seconds(4));

events::add(done, now + std::chrono::seconds(6));

while (true)
{
    usleep(10000);  // TODO: Do some "real" work here instead...
    events::timer();
}

上記の例は次のように出力します。

fooからこんにちは
バーからこんにちは::こんにちは
終わり!

2秒ごとに1行が印刷されます。プログラムが永久にループした後"Done!"は、何もしません。

このプログラムには多くのC++11機能が含まれていますが、GCC4.4.5および4.7.1でテストされていることに注意してください。残念ながら、VC ++ 2010にはヘッダーがありません<chrono>が、VC++2012RCにはヘッダーがあるようです。

于 2012-08-08T14:19:12.153 に答える
0

問題は、浮動小数点比較が原因である可能性があります。これにより、予期しない結果が生じる可能性があります。これは避けてください。

このリンクを参照してください

于 2012-08-08T13:32:30.013 に答える
0

CLOCKS_PER_SEC はシステムの整数です。他のシステムでは、float にすることもできます。その近くにも置く(浮かせる)

于 2012-08-08T13:24:06.740 に答える