- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

# Timer.h

    00001 /*
    00002  *  Phusion Passenger - http://www.modrails.com/
    00003  *  Copyright (c) 2010 Phusion
    00004  *
    00005  *  "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
    00006  *
    00007  *  Permission is hereby granted, free of charge, to any person obtaining a copy
    00008  *  of this software and associated documentation files (the "Software"), to deal
    00009  *  in the Software without restriction, including without limitation the rights
    00010  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    00011  *  copies of the Software, and to permit persons to whom the Software is
    00012  *  furnished to do so, subject to the following conditions:
    00013  *
    00014  *  The above copyright notice and this permission notice shall be included in
    00015  *  all copies or substantial portions of the Software.
    00016  *
    00017  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    00018  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    00019  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    00020  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    00021  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    00022  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    00023  *  THE SOFTWARE.
    00024  */
    00025 #ifndef _PASSENGER_TIMER_H_
    00026 #define _PASSENGER_TIMER_H_
    00027
    00028 #include <boost/thread.hpp>
    00029 #include <oxt/system_calls.hpp>
    00030 #include <sys/time.h>
    00031 #include <cerrno>
    00032
    00033 namespace Passenger {
    00034
    00035 using namespace boost;
    00036 using namespace oxt;
    00037
    00038 /**
    00039  * A Timer which one can use to check how much time has elapsed since the
    00040  * timer started. This timer support miliseconds-resolution, but the exact
    00041  * resolution depends on the OS and the hardware.
    00042  *
    00043  * This class is thread-safe.
    00044  *
    00045  * @code
    00046  * Timer timer;
    00047  * sleep(10);
    00048  * timer.elapsed();   // => about 10000 (msec)
    00049  * @endcode
    00050  */
    00051 class Timer {
    00052 private:
    00053         struct timeval startTime;
    00054         mutable boost::mutex lock;
    00055 public:
    00056         /**
    00057          * Creates a new Timer object.
    00058          *
    00059          * @param startNow Whether the timer should be started immediately.
    00060          */
    00061         Timer(bool startNow = true) {
    00062                 if (startNow) {
    00063                         start();
    00064                 } else {
    00065                         stop();
    00066                 }
    00067         }
    00068
    00069         /**
    00070          * Start the timer. If the timer was already started, then this will
    00071          * restart the timer.
    00072          */
    00073         void start() {
    00074                 // TODO: We really use should clock_gettime() and the monotonic
    00075                 // clock whenever possible, instead of gettimeofday()...
    00076                 lock_guard<boost::mutex> l(lock);
    00077                 int ret;
    00078                 do {
    00079                         ret = gettimeofday(&startTime, NULL);
    00080                 } while (ret == -1 && errno == EINTR);
    00081         }
    00082
    00083         /**
    00084          * Stop the timer. If there's currently another thread waiting on the wait()
    00085          * call, then that wait() call will block indefinitely until you call start()
    00086          * and sufficient amount of time has elapsed.
    00087          */
    00088         void stop() {
    00089                 lock_guard<boost::mutex> l(lock);
    00090                 startTime.tv_sec = 0;
    00091                 startTime.tv_usec = 0;
    00092         }
    00093
    00094         /**
    00095          * Returns the amount of time that has elapsed since the timer was last started,
    00096          * in miliseconds. If the timer is currently stopped, then 0 is returned.
    00097          */
    00098         unsigned long long elapsed() const {
    00099                 lock_guard<boost::mutex> l(lock);
    00100                 if (startTime.tv_sec == 0 && startTime.tv_usec == 0) {
    00101                         return 0;
    00102                 } else {
    00103                         struct timeval t;
    00104                         unsigned long long now, beginning;
    00105                         int ret;
    00106
    00107                         do {
    00108                                 ret = gettimeofday(&t, NULL);
    00109                         } while (ret == -1 && errno == EINTR);
    00110                         now = (unsigned long long) t.tv_sec * 1000 + t.tv_usec / 1000;
    00111                         beginning = (unsigned long long) startTime.tv_sec * 1000 + startTime.tv_usec / 1000;
    00112                         return now - beginning;
    00113                 }
    00114         }
    00115
    00116         /**
    00117          * Wait until <em>time</em> miliseconds have elapsed since the timer
    00118          * was last started.
    00119          */
    00120         void wait(unsigned long long time) const {
    00121                 while (elapsed() < time) {
    00122                         syscalls::usleep(25000);
    00123                 }
    00124         }
    00125 };
    00126
    00127 } // namespace Passenger
    00128
    00129 #endif /* _PASSENGER_TIMER_H_ */