UniSet  2.6.0
HourGlass.h
00001 /*
00002  * Copyright (c) 2015 Pavel Vainerman.
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU Lesser General Public License as
00006  * published by the Free Software Foundation, version 2.1.
00007  *
00008  * This program is distributed in the hope that it will be useful, but
00009  * WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00011  * Lesser General Lesser Public License for more details.
00012  *
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00015  */
00016 // --------------------------------------------------------------------------
00017 // idea: lav@etersoft.ru
00018 // implementation: pv@etersoft.ru, lav@etersoft.ru
00019 // --------------------------------------------------------------------------
00020 #ifndef HourGlass_H_
00021 #define HourGlass_H_
00022 // --------------------------------------------------------------------------
00023 #include "PassiveTimer.h"
00024 // --------------------------------------------------------------------------
00025 namespace uniset
00026 {
00061 class HourGlass
00062 {
00063     public:
00064         HourGlass() noexcept {}
00065         ~HourGlass() noexcept {}
00066 
00067         // запустить часы (заново)
00068         inline void run( timeout_t msec ) noexcept
00069         {
00070             t.setTiming(msec);
00071             _state   = true;
00072             _sand    = msec;
00073             _size    = msec;
00074         }
00075 
00076         inline void reset() noexcept
00077         {
00078             run(_size);
00079         }
00080 
00081         // "ёмкость" песочных часов..
00082         inline timeout_t duration() const noexcept
00083         {
00084             return _size;
00085         }
00086         // перевернуть часы
00087         // true - засечь время
00088         // false - перевернуть часы (обратный ход)
00089         // возвращает аргумент (т.е. идёт ли отсчёт времени)
00090         inline bool rotate( bool st ) noexcept
00091         {
00092             if( st == _state )
00093                 return st;
00094 
00095             _state = st;
00096 
00097             // TODO 24.10.2015 Lav: follow code is very simular to remain function
00098             if( !_state )
00099             {
00100                 timeout_t cur = t.getCurrent();
00101 
00102                 if( cur > _size )
00103                     cur = _size;
00104 
00105                 _sand = ( _sand > cur ) ? (_sand - cur) : 0;
00106 
00107                 t.setTiming(cur);
00108             }
00109             else
00110             {
00111                 timeout_t cur = t.getCurrent();
00112 
00113                 if( cur > _size )
00114                     cur = _size;
00115 
00116                 _sand += cur;
00117 
00118                 if( _sand > _size )
00119                     _sand = _size;
00120 
00121                 t.setTiming(_sand);
00122             }
00123 
00124             return st;
00125         }
00126 
00127         // получить прошедшее время
00128         inline timeout_t current() const noexcept
00129         {
00130             return t.getCurrent();
00131         }
00132 
00133         // получить заданное время
00134         inline timeout_t interval() const noexcept
00135         {
00136             return t.getInterval();
00137         }
00138 
00139         // проверить наступление
00140         inline bool check() const noexcept
00141         {
00142             // пока часы не "стоят"
00143             // всегда false
00144             if( !_state )
00145                 return false;
00146 
00147             return t.checkTime();
00148         }
00149 
00150         inline bool enabled() const noexcept
00151         {
00152             return _state;
00153         }
00154 
00155         // текущее "насыпавшееся" количество "песка" (прошедшее время)
00156         inline timeout_t amount() const noexcept
00157         {
00158             return ( _size - remain() );
00159         }
00160 
00161         // остаток песка (времени) (оставшееся время)
00162         inline timeout_t remain() const noexcept
00163         {
00164             timeout_t c = t.getCurrent();
00165 
00166             if( c > _size )
00167                 c = _size;
00168 
00169             // _state=false - означает, что песок пересыпается обратно..
00170             if( !_state )
00171             {
00172                 timeout_t ret = ( _sand + c );
00173 
00174                 if( ret > _size )
00175                     return _size;
00176 
00177                 return ret;
00178             }
00179 
00180             // _state=true  - означает, что песок пересыпается..
00181             int ret = ( _sand - c );
00182 
00183             if( ret < 0 )
00184                 return 0;
00185 
00186             return ret;
00187         }
00188 
00189     protected:
00190         PassiveTimer t;   
00191         bool _state = { false };      
00192         timeout_t _sand = { 0 };  
00193         timeout_t _size = { 0 };  
00194 };
00195 // -------------------------------------------------------------------------
00196 } // end of uniset namespace
00197 // --------------------------------------------------------------------------
00198 #endif
00199 // --------------------------------------------------------------------------