待ち処理 続き

前回の記事を書いた後に、
「ミリ秒未満の端数分だけ、while ループで待ち処理すればいいんじゃね?」
と、思い改良しました。
使い勝手は前回と変わらず。

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

#include <Windows.h>

#include "sleep.hpp"

#include <iostream>

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

    // Sleep(30) + while loop
    sleep( chrono::milliseconds(30) + chrono::microseconds(500) );
    
    return 0;
}

ミリ秒以上は、WINAPI の Sleep() で処理を行ない、
ミリ秒未満の値は、while loop を使用して待ち処理を行っています。
ハイブリットってやつです。
実装側のコードがだいぶすっきりしました。
以下、sleep.hpp のコード。

#ifndef _KMT_EX_SLEEP_H_
#define _KMT_EX_SLEEP_H_


namespace kmt_ex{


namespace detail{

    template <typename Rep, typename Period>
    void
    sleep_while_loop(const boost::chrono::duration<Rep, Period>& time){
        boost::chrono::timer<>    timer;
        while(timer.elapsed() < time);
    }
    
#ifdef WINAPI


    void
    sleep_win_api_sleep(const boost::chrono::milliseconds& time){
        Sleep(static_cast<DWORD>(time.count()) );
    }
    
#endif

}        // namespace detail


#ifdef WINAPI

/**
    ミリ秒以上の値は、WINAPI の Sleep() で待ち処理を行ないない、
    ミリ秒未満の値は、while loop で待ち処理を行う
*/
template <
    typename Rep, typename Period
>
void
sleep(const boost::chrono::duration<Rep, Period>& wait_time){
    namespace chrono = boost::chrono;
    chrono::milliseconds    ms = chrono::duration_cast<chrono::milliseconds>(wait_time);
    chrono::nanoseconds        ns = wait_time - ms;
    detail::sleep_win_api_sleep(ms);
    detail::sleep_while_loop(ns);
}

#else

/**
    while loop で待ち処理を行う
*/
template <
    typename Rep, typename Period
>
void
sleep(const boost::chrono::duration<Rep, Period>& wait_time){
    detail::sleep_while_loop(wait_time);
}

#endif

}        // namespace kmt_ex

#endif