All Classes Namespaces Files Functions Variables Enumerations Enumerator
libs/system/CycleTimer.cpp
Go to the documentation of this file.
00001 
00010 #include "CycleTimer.h"
00011 #include "ticks.h"
00012 #include <limits>
00013 
00014 using namespace qrk;
00015 using namespace std;
00016 
00017 
00018 namespace
00019 {
00020     size_t fps2msec(size_t fps)
00021     {
00022         if (fps == 0) {
00023             // 最大 fps の制限
00024             return numeric_limits<size_t>::max();
00025         }
00026 
00027         size_t msec = 1000 / fps;
00028         return max(msec, static_cast<size_t>(1));
00029     }
00030 
00031 
00032     size_t msec2fps(size_t msec)
00033     {
00034         // 1000 / msec となるので、fps2msec() の計算で済ませる
00035         return fps2msec(msec);
00036     }
00037 }
00038 
00039 
00040 struct CycleTimer::pImpl
00041 {
00042     enum {
00043         InvalidTicks = -1,
00044     };
00045 
00046     size_t cycle_msec_;
00047     int prev_ticks_;
00048     bool strict_cycle_;
00049 
00050 
00051     pImpl(void)
00052         : cycle_msec_(fps2msec(DefaultFps)), prev_ticks_(InvalidTicks),
00053           strict_cycle_(false)
00054     {
00055     }
00056 
00057 
00058     size_t waitMsec(void)
00059     {
00060         if (prev_ticks_ == InvalidTicks) {
00061             // 最初の呼び出しのときは、特に待たない
00062             prev_ticks_ = ticks();
00063             return 0;
00064         }
00065 
00066         int to_next_cycle = toNextCycleMsec();
00067         prev_ticks_ += static_cast<int>(cycle_msec_);
00068 
00069         return (to_next_cycle > 0) ? to_next_cycle : 0;
00070     }
00071 
00072 
00073     void reset(void)
00074     {
00075         prev_ticks_ = ticks();
00076     }
00077 
00078 
00079     int toNextCycleMsec(void)
00080     {
00081         int next_ticks = prev_ticks_ + static_cast<int>(cycle_msec_);
00082 
00083         int current_ticks = ticks();
00084         int to_next_cycle = next_ticks - current_ticks;
00085         if (to_next_cycle > 0) {
00086             return to_next_cycle;
00087         }
00088 
00089         if (! strict_cycle_) {
00090             if (to_next_cycle >= 0) {
00091                 to_next_cycle %= cycle_msec_;
00092             } else {
00093                 prev_ticks_ = current_ticks;
00094             }
00095         }
00096 
00097         return to_next_cycle;
00098     }
00099 };
00100 
00101 
00102 CycleTimer::CycleTimer(void) : pimpl(new pImpl)
00103 {
00104 }
00105 
00106 
00107 CycleTimer::~CycleTimer(void)
00108 {
00109 }
00110 
00111 
00112 size_t CycleTimer::waitMsec(void)
00113 {
00114     return pimpl->waitMsec();
00115 }
00116 
00117 
00118 void CycleTimer::reset(void)
00119 {
00120     pimpl->reset();
00121 }
00122 
00123 
00124 void CycleTimer::setStrictCycle(bool on)
00125 {
00126     pimpl->strict_cycle_ = on;
00127 }
00128 
00129 
00130 void CycleTimer::setCycleFps(size_t fps)
00131 {
00132     pimpl->cycle_msec_ = fps2msec(fps);
00133 }
00134 
00135 
00136 size_t CycleTimer::cycleFps(void) const
00137 {
00138     return msec2fps(pimpl->cycle_msec_);
00139 }
00140 
00141 
00142 void CycleTimer::setCycleMsec(size_t msec)
00143 {
00144     pimpl->cycle_msec_ = msec;
00145 }
00146 
00147 
00148 size_t CycleTimer::cycleMsec(void) const
00149 {
00150     return pimpl->cycle_msec_;
00151 }
00152 
00153 
00154 int CycleTimer::toNextCycleMsec(void)
00155 {
00156     return pimpl->toNextCycleMsec();
00157 }