待ち処理

WINAPI の Sleep() に chrono::duration で定義されている単位で渡したかったのでラップしました。
ついでにミリ秒未満なら while ループで待ち処理も実装。

#include <boost/chrono.hpp>
#include <boost/chrono/timer.hpp>
#include <boost/utility/enable_if.hpp>

#include <Windows.h>

#include "sleep.hpp"

int
main(){
    
    using kmt_ex::sleep;
    namespace chrono = boost::chrono;

    sleep( chrono::milliseconds(30) );    // WINAPI Sleep();
    sleep( chrono::nanoseconds(50) );     // while loop
    sleep( chrono::seconds(1) );          // WINAPI Sleep();
    sleep( chrono::microseconds(40) );    // while loop

    sleep( chrono::nanoseconds(chrono::seconds(1)) );    // while loop
    
    return 0;
}

それぞれの単位の時に呼ばれる処理は上記の通り。
Windows.h がインクルードされていない場合は、while ループの方で待ち処理を行います。
while ループで待つ場合は、CPUが全力駆動するので重くなります。
C/C++ って、Sleep() 以外の待ち処理ってないんでしょうか。
UNIX 系やスレッド周りの待ち処理ってどうやって実装してるんだろう。


ところで、今回は、Windows.h のインクルードの有無を WINAPI の定義で判断してるけど
これで合ってるかどうかは不明。

以下、sleep.hpp の中身。

#ifndef _KMT_EX_SLEEP_H_
#define _KMT_EX_SLEEP_H_

namespace kmt_ex{

namespace detail{

#ifdef WINAPI

    using boost::enable_if;
    using boost::ratio_less;
    using boost::ratio_greater_equal;

    /**
        Period < milliseconds の場合に呼ばれる
    */
    template<typename Period>
    void
    sleep_impl(
        const boost::chrono::nanoseconds& wait_time,
        typename enable_if<ratio_less<Period, boost::milli> >::type* = 0
    ){
        boost::chrono::timer<>    timer;
        while(timer.elapsed() < wait_time);
    }

    /**
        Period >= milliseconds の場合に呼ばれる
    */
    template<typename Period>
    void
    sleep_impl(
        const boost::chrono::milliseconds& wait_time,
        typename enable_if<ratio_greater_equal<Period, boost::milli> >::type* = 0
    ){
        Sleep(static_cast<DWORD>(wait_time.count()) );
    }

#else

    /**
        Windows.h をインクルードしていない場合は、while loop で待ち処理
    */
    template<typename T>
    void
    sleep_impl(const boost::chrono::nanoseconds& wait_time){
        boost::chrono::timer<>    timer;
        while(timer.elapsed() < wait_time);
    }

#endif

}        // namespace detail

/**
    待ち処理
*/
template <
    typename Rep, typename Period
>
void
sleep(const boost::chrono::duration<Rep, Period>& wait_time){
    detail::sleep_impl<Period>(wait_time);
}

}        // namespace kmt_ex

#endif