Fawkes API  Fawkes Development Version
wait.cpp
00001 
00002 /***************************************************************************
00003  *  wait.cpp - TimeWait tool
00004  *
00005  *  Created: Thu Nov 29 17:30:37 2007
00006  *  Copyright  2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <utils/time/wait.h>
00025 #include <utils/time/time.h>
00026 #include <utils/time/clock.h>
00027 
00028 #include <unistd.h>
00029 #include <cstdlib>
00030 
00031 namespace fawkes {
00032 
00033 /** @class TimeWait <utils/time/wait.h>
00034  * Time wait utility.
00035  * This class allows for guaranteed waiting for a specified amout of time. It can
00036  * either be used to suspend the current thread for at least the given time (static
00037  * methods) or it can be used to reach a desired minimum loop time. For this instantiate
00038  * the class and call set_start() at the beginning of the loop and wait() at the end.
00039  * wait() will then suspend the thread as long as needed to have the desired minimum
00040  * loop time. The TimeWait utility will use the current clock time. Thus it may wait
00041  * for a given amount of say simulated time.
00042  * @author Tim Niemueller
00043  */
00044 
00045 /** Constructor.
00046  * @param clock clock to use
00047  * @param desired_loop_time_usec desired minimum loop time in microseconds
00048  */
00049 TimeWait::TimeWait(Clock *clock, long int desired_loop_time_usec)
00050 {
00051   __desired_loop_time = desired_loop_time_usec;
00052   __clock = clock;
00053   __until = new Time();
00054   __until_systime = new Time();
00055   __now = new Time();
00056 }
00057 
00058 
00059 /** Destructor. */
00060 TimeWait::~TimeWait()
00061 {
00062   delete __until;
00063   delete __until_systime;
00064   delete __now;
00065 }
00066 
00067 
00068 /** Mark start of loop. */
00069 void
00070 TimeWait::mark_start()
00071 {
00072   __clock->get_time(__until);
00073   *__until += __desired_loop_time;
00074   __clock->get_systime(__until_systime);
00075   *__until_systime += __desired_loop_time;
00076 }
00077 
00078 
00079 /** Wait until minimum loop time has been reached. */
00080 void
00081 TimeWait::wait()
00082 {
00083   __clock->get_time(__now);
00084   // we want to release run status at least shortly
00085   usleep(0);
00086 
00087   long int remaining_usec = (*__until - *__now).in_usec();
00088   while ( remaining_usec > 0 ) {
00089     usleep(remaining_usec);
00090     __clock->get_time(__now);
00091     remaining_usec = (*__until - *__now).in_usec();
00092   }
00093 }
00094 
00095 
00096 /** Wait until minimum loop time has been reached in real time.
00097  * This uses the system time and not an external time source if defined.
00098  */
00099 void
00100 TimeWait::wait_systime()
00101 {
00102   __clock->get_systime(__now);
00103   // we want to release run status at least shortly
00104   usleep(0);
00105 
00106   long int remaining_usec = (*__until_systime - *__now).in_usec();
00107   while ( remaining_usec > 0 ) {
00108     usleep(remaining_usec);
00109     __clock->get_systime(__now);
00110     remaining_usec = (*__until_systime - *__now).in_usec();
00111   }
00112 }
00113 
00114 
00115 /** Wait at least usec microseconds.
00116  * Think of this as an uninterruptible usleep(). This method will not return before
00117  * *at least* usec microseconds have passed. It may be longer but never less.
00118  * Time is tracked in system time scale (real time).
00119  * @param usec number of microseconds to wait at least
00120  */
00121 void
00122 TimeWait::wait_systime(long int usec)
00123 {
00124   if ( usec < 0 ) return;
00125   struct timeval start, now;
00126   long int remaining_usec = usec;
00127   gettimeofday(&start, NULL);
00128   do {
00129     usleep(remaining_usec);
00130     gettimeofday(&now, NULL);
00131   } while ((remaining_usec = usec - time_diff_usec(now, start)) > 0);
00132 }
00133 
00134 /** Wait at least usec microseconds.
00135  * Think of this as an uninterruptible usleep(). This method will not return before
00136  * *at least* usec microseconds have passed. It may be longer but never less.
00137  * Time is tracked in the current Clock time scale. This may be simulated time
00138  * or real time. It is assumed that the (simulated time) is at worst slower, but never
00139  * faster than real time. Thus 1 microsecond real time is at least 1 microsecond clock time.
00140  * @param usec number of microseconds to wait at least
00141  */
00142 void
00143 TimeWait::wait(long int usec)
00144 {
00145   if ( usec < 0 ) return;
00146   Clock *clock = Clock::instance();
00147   struct timeval start, now;
00148   long int remaining_usec = usec;
00149   clock->get_time(&start);
00150   do {
00151     usleep(remaining_usec);
00152     clock->get_time(&now);
00153   } while ((remaining_usec = usec - time_diff_usec(now, start)) > 0);
00154 }
00155 
00156 } // end namespace fawkes