- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List

# SystemTime.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_SYSTEM_TIME_H_
    00026 #define _PASSENGER_SYSTEM_TIME_H_
    00027
    00028 #include <boost/thread.hpp>
    00029 #include <oxt/system_calls.hpp>
    00030 #include "Exceptions.h"
    00031
    00032 namespace Passenger {
    00033
    00034 using namespace oxt;
    00035
    00036 namespace SystemTimeData {
    00037         extern bool hasForcedValue;
    00038         extern time_t forcedValue;
    00039         extern bool hasForcedMsecValue;
    00040         extern unsigned long long forcedMsecValue;
    00041         extern bool hasForcedUsecValue;
    00042         extern unsigned long long forcedUsecValue;
    00043 }
    00044
    00045 /**
    00046  * This class allows one to obtain the system time, similar to time() and
    00047  * gettimeofday(). Unlike time(), it is possible to force a certain time
    00048  * to be returned, which is useful for testing code that depends on the
    00049  * system time.
    00050  *
    00051  * get() provides seconds resolution while getMsec() provides milliseconds
    00052  * resolution. Both clocks can be independently forced to a certain value
    00053  * through force() and forceMsec().
    00054  */
    00055 class SystemTime {
    00056 public:
    00057         /**
    00058          * Returns the time since the Epoch, measured in seconds. Or, if a time
    00059          * was forced with force(), then the forced time is returned instead.
    00060          *
    00061          * @throws TimeRetrievalException Something went wrong while retrieving the time.
    00062          * @throws boost::thread_interrupted
    00063          */
    00064         static time_t get() {
    00065                 if (SystemTimeData::hasForcedValue) {
    00066                         return SystemTimeData::forcedValue;
    00067                 } else {
    00068                         time_t ret = syscalls::time(NULL);
    00069                         if (ret == -1) {
    00070                                 int e = errno;
    00071                                 throw TimeRetrievalException(
    00072                                         "Unable to retrieve the system time",
    00073                                         e);
    00074                         }
    00075                         return ret;
    00076                 }
    00077         }
    00078
    00079         /**
    00080          * Returns the time since the Epoch, measured in milliseconds. Or, if a
    00081          * time was forced with forceMsec(), then the forced time is returned instead.
    00082          *
    00083          * @throws TimeRetrievalException Something went wrong while retrieving the time.
    00084          * @throws boost::thread_interrupted
    00085          */
    00086         static unsigned long long getMsec() {
    00087                 if (SystemTimeData::hasForcedMsecValue) {
    00088                         return SystemTimeData::forcedMsecValue;
    00089                 } else {
    00090                         struct timeval t;
    00091                         int ret;
    00092
    00093                         do {
    00094                                 ret = gettimeofday(&t, NULL);
    00095                         } while (ret == -1 && errno == EINTR);
    00096                         if (ret == -1) {
    00097                                 int e = errno;
    00098                                 throw TimeRetrievalException(
    00099                                         "Unable to retrieve the system time",
    00100                                         e);
    00101                         }
    00102                         return (unsigned long long) t.tv_sec * 1000 + t.tv_usec / 1000;
    00103                 }
    00104         }
    00105
    00106         /**
    00107          * Returns the time since the Epoch, measured in microseconds. Or, if a
    00108          * time was forced with forceUsec(), then the forced time is returned instead.
    00109          *
    00110          * @throws TimeRetrievalException Something went wrong while retrieving the time.
    00111          * @throws boost::thread_interrupted
    00112          */
    00113         static unsigned long long getUsec() {
    00114                 if (SystemTimeData::hasForcedUsecValue) {
    00115                         return SystemTimeData::forcedUsecValue;
    00116                 } else {
    00117                         struct timeval t;
    00118                         int ret;
    00119
    00120                         do {
    00121                                 ret = gettimeofday(&t, NULL);
    00122                         } while (ret == -1 && errno == EINTR);
    00123                         if (ret == -1) {
    00124                                 int e = errno;
    00125                                 throw TimeRetrievalException(
    00126                                         "Unable to retrieve the system time",
    00127                                         e);
    00128                         }
    00129                         return (unsigned long long) t.tv_sec * 1000000 + t.tv_usec;
    00130                 }
    00131         }
    00132
    00133         /**
    00134          * Force get() to return the given value.
    00135          */
    00136         static void force(time_t value) {
    00137                 SystemTimeData::hasForcedValue = true;
    00138                 SystemTimeData::forcedValue = value;
    00139         }
    00140
    00141         /**
    00142          * Force getMsec() to return the given value.
    00143          */
    00144         static void forceMsec(unsigned long long value) {
    00145                 SystemTimeData::hasForcedMsecValue = true;
    00146                 SystemTimeData::forcedMsecValue = value;
    00147         }
    00148
    00149         /**
    00150          * Force getUsec() to return the given value.
    00151          */
    00152         static void forceUsec(unsigned long long value) {
    00153                 SystemTimeData::hasForcedUsecValue = true;
    00154                 SystemTimeData::forcedUsecValue = value;
    00155         }
    00156
    00157         /**
    00158          * Release the previously forced seconds value, so that get()
    00159          * returns the system time once again.
    00160          */
    00161         static void release() {
    00162                 SystemTimeData::hasForcedValue = false;
    00163         }
    00164
    00165         /**
    00166          * Release the previously forced msec value, so that getMsec()
    00167          * returns the system time once again.
    00168          */
    00169         static void releaseMsec() {
    00170                 SystemTimeData::hasForcedMsecValue = false;
    00171         }
    00172
    00173         /**
    00174          * Release the previously forced usec value, so that getUsec()
    00175          * returns the system time once again.
    00176          */
    00177         static void releaseUsec() {
    00178                 SystemTimeData::hasForcedUsecValue = false;
    00179         }
    00180
    00181         /**
    00182          * Release all previously forced values, so that get(), getMsec()
    00183          * and getUsec() return the system time once again.
    00184          */
    00185         static void releaseAll() {
    00186                 SystemTimeData::hasForcedValue = false;
    00187                 SystemTimeData::hasForcedMsecValue = false;
    00188                 SystemTimeData::hasForcedUsecValue = false;
    00189         }
    00190 };
    00191
    00192 } // namespace Passenger
    00193
    00194 #endif /* _PASSENGER_SYSTEM_TIME_H_ */