WvStreams
wvtimestream.cc
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * See wvtimestream.h.
00006  */
00007 #include "wvtimestream.h"
00008 
00009 WvTimeStream::WvTimeStream():
00010     last(wvtime_zero), next(wvtime_zero), ms_per_tick(0)
00011 {
00012 }
00013 
00014 
00015 void WvTimeStream::set_timer(time_t msec)
00016 {
00017     WvTime now = wvstime();
00018 
00019     ms_per_tick = msec > 0 ? msec : 0;
00020     next = msecadd(now, ms_per_tick);
00021     last = now;
00022 }
00023 
00024 
00025 bool WvTimeStream::isok() const
00026 {
00027     return true;
00028 }
00029 
00030 
00031 void WvTimeStream::pre_select(SelectInfo &si)
00032 {
00033     WvTime now;
00034     time_t diff;
00035     WvStream::pre_select(si);
00036     
00037     //fprintf(stderr, "%p: timestream pre_select mspt=%ld msto=%ld\n",
00038     //     this, ms_per_tick, si.msec_timeout);
00039 
00040     if (ms_per_tick)
00041     {
00042         now = wvstime();
00043         
00044         /* Are we going back in time? If so, adjust the due time. */
00045         if (now < last)
00046             next = tvdiff(next, tvdiff(last, now));
00047         
00048         last = now;
00049 
00050         if (next <= now)
00051         {
00052             si.msec_timeout = 0;
00053             return;
00054         }
00055 
00056         diff = msecdiff(next, now);
00057         diff = diff < 0 ? 0 : diff;
00058         if (diff < si.msec_timeout || si.msec_timeout < 0)
00059             si.msec_timeout = diff;
00060     }
00061 }
00062 
00063 
00064 bool WvTimeStream::post_select(SelectInfo &si)
00065 {
00066     WvTime now = wvstime();
00067 
00068     return WvStream::post_select(si) || (ms_per_tick && next <= now);
00069 }
00070 
00071 
00072 void WvTimeStream::execute()
00073 {
00074     WvStream::execute();
00075 
00076     /* Schedule our next timer event, unless alarm_is_ticking, which
00077      * would mean that we're here because someone used alarm() rather
00078      * than because our timer expired. */
00079     if (!alarm_was_ticking)
00080     {
00081         WvTime now = wvstime();
00082 
00083         next = msecadd(next, ms_per_tick);
00084         
00085         if (msecdiff(next, now) > ms_per_tick * 100 || 
00086             msecdiff(now, next) > ms_per_tick * 100)
00087         {
00088             // reset if we fall forward or behind WAY too excessively
00089             // This is usually due to a change in system time
00090             last = now;
00091             next = msecadd(last, ms_per_tick);
00092         }
00093         else if (msecdiff(next, now) > ms_per_tick * 10)
00094             // compensate if we fall behind too excessively
00095             next = msecadd(now, ms_per_tick);
00096     }
00097 }