Back to index

nux  3.0.0
TimerProc.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 
00023 #include "Nux.h"
00024 #include "TimerProc.h"
00025 #include "WindowCompositor.h"
00026 #include "WindowThread.h"
00027 
00028 class BaseWindow;
00029     
00030 namespace nux
00031 {
00032 
00033   typedef struct
00034   {
00035     long    sec;         // seconds
00036     long    usec;        // and microseconds
00037   } TimeStruct;
00038 
00042   static bool TimeIsGreater(TimeStruct t1, TimeStruct t2);
00043   static void TimeRightNow(TimeStruct *tv);
00044   static void Addmillisecs(TimeStruct *tv, unsigned int milliseconds);
00045 //static unsigned int TimeDiff(TimeStruct t1, TimeStruct t2);
00046 
00047   static NThreadSafeCounter TimerUID = 0x01234567;
00048 
00049   class TimerObject
00050   {
00051   public:
00052     TimerObject();
00053 
00054     bool operator == (const TimerObject &timer_object);
00055 
00057     TimeStruct      when;
00058     void            *CallbackData;
00059     TimeOutSignal    *timeout_signal;
00060 
00062     float           Param;
00063     float           ProgressDelta;
00064     int             Type;
00065     int             ScheduledIteration;     
00066     int             ProgressIterationCount; 
00067     int             Period;                 
00068     int             Duration;               
00069     int             ElapsedTime;            
00070     bool            MarkedForRemoval;
00071     BaseWindow      *Window;                 
00072     TimerObject     *next;
00073     TimerObject     *prev;
00074     unsigned int           glibid;
00075     unsigned int           uid;
00076   };
00077 
00078   TimerObject::TimerObject()
00079   {
00080     Type            = 0;
00081     CallbackData    = 0;
00082     timeout_signal   = 0;
00083     Param           = 0;
00084     Period          = 0;
00085     Duration        = 0;
00086     ElapsedTime     = 0;
00087     ScheduledIteration       = 0;
00088     ProgressIterationCount  = 0;
00089     MarkedForRemoval = 0;
00090     Window          = 0;
00091     next            = 0;
00092     prev            = 0;
00093     glibid          = 0;
00094     uid             = 0;
00095   }
00096 
00097   TimerHandle::TimerHandle()
00098   {
00099     m_d = 0;
00100   }
00101 
00102   TimerHandle::TimerHandle(TimerObject *timer_object)
00103   {
00104     m_d = timer_object;
00105   }
00106 
00107   TimerHandle::~TimerHandle()
00108   {
00109     m_d = 0;
00110   }
00111 
00112   TimerHandle::TimerHandle(const TimerHandle &timer_handle)
00113   {
00114     m_d = timer_handle.m_d;
00115   }
00116 
00117   TimerHandle &TimerHandle::operator = (const TimerHandle &timer_handle)
00118   {
00119     m_d = timer_handle.m_d;
00120     return *this;
00121   }
00122 
00123   bool TimerHandle::IsValid() const
00124   {
00125     return Activated();
00126   }
00127 
00128   bool TimerHandle::Activated() const
00129   {
00130     return m_d != 0;
00131   }
00132 
00133   float TimerHandle::GetProgress() const
00134   {
00135     if (m_d)
00136       return m_d->Param;
00137     return 0.0f;
00138   }
00139 
00140   float TimerHandle::GetProgressDelta() const
00141   {
00142     if (m_d)
00143       return m_d->ProgressDelta;
00144     return 0;
00145   }
00146 
00147   int TimerHandle::GetScheduledIterationCount() const
00148   {
00149     if (m_d)
00150       return m_d->ScheduledIteration;
00151     return 0;
00152   }
00153 
00154   int TimerHandle::GetProgressIterationCount() const
00155   {
00156     if (m_d)
00157       return m_d->ProgressIterationCount;
00158     return 0;
00159   }
00160 
00161   int TimerHandle::GetElapsedTimed() const
00162   {
00163     if (m_d)
00164       return m_d->ElapsedTime;
00165     return 0;
00166   }
00167 
00169   TimerHandler::TimerHandler(WindowThread* window_thread)
00170   : window_thread_(window_thread)
00171   {
00172     m_timer_object_queue = 0;
00173     m_IsProceesingTimers = false;
00174   }
00175 
00176   TimerHandler::~TimerHandler()
00177   {
00178 
00179   }
00180 
00181   void TimerHandler::StartEarlyTimerObjects()
00182   {
00183     std::list<TimerObject*>::iterator it;
00184     for (it = _early_timer_objects.begin(); it != _early_timer_objects.end(); it++)
00185     {
00186       TimerObject *timer_object = *it;
00187       TimeRightNow(&timer_object->when);
00188       Addmillisecs(&timer_object->when, timer_object->Period);
00189 
00190 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00191         timer_object->glibid = GetWindowThread()->AddTimeout(timer_object->Period);
00192 #endif
00193     }
00194 
00195     _early_timer_objects.clear();
00196   }
00197 
00198   TimerHandle TimerHandler::AddTimerHandler(unsigned int Period, TimeOutSignal *timeout_signal, void *Data, WindowThread* window_thread)
00199   {
00200     TimerObject *timer_object = new TimerObject();
00201 
00202     TimeRightNow(&timer_object->when);
00203     Addmillisecs(&timer_object->when, Period);
00204 
00205     timer_object->CallbackData  = Data;
00206     timer_object->timeout_signal = timeout_signal;
00207     timer_object->Period        = Period;
00208     timer_object->Type          = TIMERTYPE_PERIODIC;
00209     if (window_thread)
00210       timer_object->Window        = window_thread->GetWindowCompositor().GetProcessingTopView();
00211     else
00212       timer_object->Window        = GetWindowThread()->GetWindowCompositor().GetProcessingTopView();
00213     
00214     AddHandle(timer_object);
00215 
00216 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00217     {
00218       if (window_thread)
00219         timer_object->glibid = window_thread->AddTimeout(Period);
00220       else
00221         timer_object->glibid = GetWindowThread()->AddTimeout(Period);
00222       
00223       if (timer_object->glibid == 0)
00224       {
00225         _early_timer_objects.push_back(timer_object);
00226         // Probably trying to set a timeout before Glib main context and loop have been created.
00227         // Sometimes later, this timer will be examined when ExecTimerHandler is called.
00228         // This happens when trying to set a callback before the mainloop has been initialized.
00229       }
00230 
00231       //nuxDebugMsg("[TimerHandler::AddTimerHandler] Adding Timeout ID: %d", timer_object->glibid);
00232     }
00233 #endif
00234 
00235     TimerHandle handle(timer_object);
00236     return handle;
00237   }
00238 
00239   TimerHandle TimerHandler::AddPeriodicTimerHandler(unsigned int Period, int Duration, TimeOutSignal *timeout_signal, void *Data)
00240   {
00241     TimerObject *timer_object = new TimerObject();
00242     TimeRightNow(&timer_object->when);
00243     Addmillisecs(&timer_object->when, Period);
00244     timer_object->CallbackData = Data;
00245     timer_object->timeout_signal = timeout_signal;
00246 
00247     timer_object->Period = Period;
00248     timer_object->Duration = (Duration < 0) ? -1 : Duration;
00249     timer_object->Type = TIMERTYPE_DURATION;
00250     AddHandle(timer_object);
00251 
00252 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00253     {
00254       timer_object->glibid = GetWindowThread()->AddTimeout(Period);
00255 
00256       if (timer_object->glibid == 0)
00257       {
00258         _early_timer_objects.push_back(timer_object);
00259         // Probably trying to set a timeout before Glib main context and loop have been created.
00260         // Sometimes later, this timer will be examined when ExecTimerHandler is called.
00261         // This happens when trying to set a callback before the mainloop has been initialized.
00262       }
00263 
00264       //nuxDebugMsg("[TimerHandler::AddTimerHandler] Adding Timeout ID: %d", timer_object->glibid);
00265     }
00266 #endif
00267 
00268     TimerHandle handle(timer_object);
00269     return handle;
00270   }
00271 
00272   TimerHandle TimerHandler::AddCountIterationTimerHandler(unsigned int Period, int NumberOfIterations, TimeOutSignal *timeout_signal, void *Data)
00273   {
00274     TimerObject *timer_object = new TimerObject();
00275     TimeRightNow(&timer_object->when);
00276     Addmillisecs(&timer_object->when, Period);
00277     timer_object->CallbackData = Data;
00278     timer_object->timeout_signal = timeout_signal;
00279 
00280     timer_object->Period = Period;
00281     timer_object->ScheduledIteration  = (NumberOfIterations < 0) ? -1 : NumberOfIterations;
00282     timer_object->Type = TIMERTYPE_ITERATION;
00283     AddHandle(timer_object);
00284 
00285 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00286     {
00287       timer_object->glibid = GetWindowThread()->AddTimeout(Period);
00288 
00289       if (timer_object->glibid == 0)
00290       {
00291         _early_timer_objects.push_back(timer_object);
00292         // Probably trying to set a timeout before Glib main context and loop have been created.
00293         // Sometimes later, this timer will be examined when ExecTimerHandler is called.
00294         // This happens when trying to set a callback before the mainloop has been initialized.
00295       }
00296 
00297       //nuxDebugMsg("[TimerHandler::AddTimerHandler] Adding Timeout ID: %d", timer_object->glibid);
00298     }
00299 #endif
00300     TimerHandle handle(timer_object);
00301     return handle;
00302   }
00303 
00304 // Sort timers and add them to the queue
00305   TimerObject *TimerHandler::AddHandle(TimerObject *timer_object)
00306   {
00307     if (timer_object == NULL)
00308       return NULL;
00309 
00310     // Give the Timer a unique ID;
00311     timer_object->uid = TimerUID.GetValue();
00312     TimerUID.Increment();
00313 
00314     // If the queue is empty or the new timer will expire sooner than the first timer in the queue
00315     // then add the new timer at the start of the queue.
00316     if ((m_timer_object_queue == NULL) || TimeIsGreater(m_timer_object_queue->when, timer_object->when))
00317     {
00318       // Add the timer timer_object at the head of the queue
00319       timer_object->next = m_timer_object_queue;
00320 
00321       if (m_timer_object_queue)
00322         m_timer_object_queue->prev = timer_object;
00323 
00324       timer_object->prev = 0;
00325       m_timer_object_queue = timer_object;
00326 
00327       return timer_object;
00328     }
00329 
00330     TimerObject *tmp = m_timer_object_queue;
00331 
00332     while (tmp->next != NULL)
00333     {
00334       // Is the time to wait for tmp->next to expire smaller than for timer_object
00335       if (TimeIsGreater(timer_object->when, tmp->next->when))
00336       {
00337         // keep searching
00338         tmp = tmp->next;
00339       }
00340       else
00341       {
00342         timer_object->next = tmp->next;
00343         tmp->next->prev = timer_object;
00344         tmp->next = timer_object;
00345         timer_object->prev = tmp;
00346         return timer_object;
00347       }
00348     }
00349 
00350     tmp->next = timer_object;
00351     timer_object->next = NULL;
00352     timer_object->prev = tmp;
00353     return timer_object;
00354   }
00355 
00356   unsigned int TimerHandler::GetNumPendingHandler()
00357   {
00358     unsigned int count = 0;
00359     TimerObject *head = m_timer_object_queue;
00360 
00361     while (head)
00362     {
00363       count++;
00364       head = head->next;
00365     }
00366 
00367     return count;
00368   }
00369 
00370   bool TimerHandler::RemoveTimerHandler(TimerHandle &timer_object)
00371   {
00372     NUX_RETURN_VALUE_IF_NULL(timer_object.m_d, false);
00373     NUX_RETURN_VALUE_IF_NULL(m_timer_object_queue, false);
00374 
00375     TimerObject *tmp;
00376 
00377     tmp = m_timer_object_queue;
00378 
00379     while (tmp)
00380     {
00381       if ((tmp == timer_object.m_d) && (tmp->uid == timer_object.m_d->uid))
00382       {
00383         if (!m_IsProceesingTimers)
00384         {
00385           if (tmp->next)
00386             tmp->next->prev = tmp->prev;
00387 
00388           if (tmp->prev)
00389             tmp->prev->next = tmp->next;
00390 
00391           if ((timer_object.m_d == m_timer_object_queue) && (timer_object.m_d->uid == m_timer_object_queue->uid))
00392             m_timer_object_queue = timer_object.m_d->next;
00393 
00394           NUX_SAFE_DELETE(timer_object.m_d);
00395         }
00396         else
00397         {
00398           timer_object.m_d->MarkedForRemoval = true;
00399         }
00400 
00401         return true;
00402       }
00403 
00404       tmp = tmp->next;
00405     }
00406 
00407     return false;
00408   }
00409 
00410 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00411   int TimerHandler::ExecTimerHandler(unsigned int timer_id)
00412 #else
00413   int TimerHandler::ExecTimerHandler()
00414 #endif
00415   {
00416     NUX_RETURN_VALUE_IF_NULL(m_timer_object_queue, 0);
00417 
00418     bool repeat = false;
00419     TimerObject *timer_object = m_timer_object_queue;
00420     TimeStruct now;
00421 
00422     int timer_executed = 0;
00423 
00424     TimeRightNow(&now);
00425 
00426     m_IsProceesingTimers = true;
00427 
00428     while (timer_object != NULL)
00429     {
00430 #if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
00431 
00432       if ((/*TimeIsGreater(now, timer_object->when) ||*/ (timer_object->glibid == timer_id)) && (timer_object->MarkedForRemoval == false))
00433 #else
00434       if (TimeIsGreater(now, timer_object->when))
00435 #endif
00436       {
00437         long elaps = now.sec - timer_object->when.sec;
00438         long uelaps = now.usec - timer_object->when.usec;
00439 
00440         if (uelaps < 0)
00441         {
00442           uelaps += 1000000;
00443           //nuxAssert(elaps > 0);
00444           elaps -= 1;
00445         }
00446 
00447         timer_object->ElapsedTime += timer_object->Period; //elaps * 1000 + uelaps / 1000; // milliseconds
00448 
00449         if (timer_object->Type == TIMERTYPE_PERIODIC)
00450         {
00451           timer_object->ProgressDelta = float(timer_object->ElapsedTime) / float(timer_object->Period) - timer_object->Param;
00452           // Clamp progress delta so(timer_object->Param + timer_object->ProgressDelta) <= 1.0f
00453           if (timer_object->Param + timer_object->ProgressDelta > 1.0f)
00454             timer_object->ProgressDelta = 1.0f - timer_object->Param;
00455 
00456           timer_object->Param = float(timer_object->ElapsedTime) / float(timer_object->Period);
00457         }
00458         else if (timer_object->Type == TIMERTYPE_DURATION)
00459         {
00460           timer_object->ProgressDelta = float(timer_object->ElapsedTime) / float(timer_object->Duration) - timer_object->Param;
00461           // Clamp progress delta so(timer_object->Param + timer_object->ProgressDelta) <= 1.0f
00462           if (timer_object->Param + timer_object->ProgressDelta > 1.0f)
00463             timer_object->ProgressDelta = 1.0f - timer_object->Param;
00464 
00465           if (timer_object->ProgressDelta < 0.0f)
00466             timer_object->ProgressDelta = 0.0f;
00467 
00468           timer_object->Param = float(timer_object->ElapsedTime) / float(timer_object->Duration);
00469         }
00470         else if (timer_object->Type == TIMERTYPE_ITERATION)
00471         {
00472           timer_object->ProgressIterationCount += 1;
00473           int duration = timer_object->Period * timer_object->ScheduledIteration;
00474 
00475           timer_object->ProgressDelta = float(timer_object->ElapsedTime) / float(duration) - timer_object->Param;
00476           // Clamp progress delta so(timer_object->Param + timer_object->ProgressDelta) <= 1.0f
00477           if (timer_object->Param + timer_object->ProgressDelta > 1.0f)
00478             timer_object->ProgressDelta = 1.0f - timer_object->Param;
00479 
00480           timer_object->Param = float(timer_object->ElapsedTime) / float(duration);
00481         }
00482         else
00483         {
00484           nuxAssertMsg(0, "[TimerHandler::ExecTimerHandler] Unknown timer type.");
00485         }
00486 
00487         if (timer_object->Param > 1.0f)
00488           timer_object->Param = 1.0f;
00489 
00490         timer_object->MarkedForRemoval = false;
00491 
00492         if (timer_object->timeout_signal != 0)
00493         {
00494           GetWindowThread()->GetWindowCompositor().SetProcessingTopView(timer_object->Window);
00495           timer_object->timeout_signal->time_expires.emit(timer_object->CallbackData);
00496           GetWindowThread()->GetWindowCompositor().SetProcessingTopView(NULL);          
00497           // Reset glibid to 0. glibid is not null, if this element ever happened to be at the head of the queue
00498           // and we set a timer for it.
00499           //nuxDebugMsg("[TimerHandler::ExecTimerHandler] Executed Timeout ID: %d", timer_object->glibid);
00500           //timer_object->glibid = 0;
00501         }
00502 
00503         TimerObject *expired_handler = 0;
00504 
00505         if (timer_object->MarkedForRemoval)
00506         {
00507           // RemoveTimerHandler was called during the callback execution
00508           expired_handler = timer_object;
00509         }
00510         else if (timer_object->Type == TIMERTYPE_PERIODIC)
00511         {
00512           expired_handler = timer_object;
00513         }
00514         else if ((timer_object->Type == TIMERTYPE_DURATION) && (timer_object->Param >= 1.0f))
00515         {
00516           expired_handler = timer_object;
00517         }
00518         else if ((timer_object->Type == TIMERTYPE_ITERATION) && (timer_object->ProgressIterationCount >= timer_object->ScheduledIteration))
00519         {
00520           expired_handler = timer_object;
00521         }
00522 
00523         if (expired_handler)
00524         {
00525           if (timer_object->next)
00526             timer_object->next->prev = timer_object->prev;
00527 
00528           if (timer_object->prev)
00529             timer_object->prev->next = timer_object->next;
00530 
00531           if ((timer_object == m_timer_object_queue) && (timer_object->uid == m_timer_object_queue->uid))
00532           {
00533             // timer_object is the first element of the queue.
00534             m_timer_object_queue = timer_object->next;
00535 
00536             if (m_timer_object_queue)
00537             {
00538               m_timer_object_queue->prev = 0;
00539             }
00540           }
00541 
00542           timer_object = timer_object->next;
00543 
00544           delete expired_handler;
00545         }
00546         else
00547         {
00548           repeat = true;
00549           //timer_object = timer_object->next;
00550         }
00551 
00552         timer_executed++;
00553         break;
00554       }
00555       else
00556       {
00557         timer_object = timer_object->next;
00558       }
00559     }
00560 
00561 //     // Look at the head of the queue and set a glib timeout for the first element, if one wasn't set already.
00562 //     if (m_timer_object_queue && (m_timer_object_queue->glibid == 0))
00563 //     {
00564 //         // How long(in milliseconds) between now and the moment the timeout expires?
00565 //         unsigned int time_difference = TimeDiff(now, m_timer_object_queue->when);
00566 //
00567 //         m_timer_object_queue->glibid = GetWindowThread()->AddTimeout(time_difference);
00568 //         //nuxDebugMsg("[TimerHandler::ExecTimerHandler] Adding Timeout ID: %d", m_timer_object_queue->glibid);
00569 //     }
00570 
00571     // Purge handles that have been marked for removal
00572     timer_object = m_timer_object_queue;
00573 
00574     while (timer_object)
00575     {
00576       if (timer_object->MarkedForRemoval)
00577       {
00578         TimerObject *expired_handler = timer_object;
00579 
00580         if (timer_object->next)
00581           timer_object->next->prev = timer_object->prev;
00582 
00583         if (timer_object->prev)
00584           timer_object->prev->next = timer_object->next;
00585         else
00586         {
00587           // timer_object is the first element of the queue.
00588           m_timer_object_queue = timer_object->next;
00589 
00590           if (m_timer_object_queue)
00591           {
00592             m_timer_object_queue->prev = 0;
00593           }
00594         }
00595 
00596         timer_object = timer_object->next;
00597         delete expired_handler;
00598       }
00599       else
00600       {
00601         timer_object = timer_object->next;
00602       }
00603     }
00604 
00605     m_IsProceesingTimers = false;
00606     //return timer_executed;
00607     return repeat;
00608   }
00609 
00610   bool TimerHandler::FindTimerHandle(TimerHandle &timer_object)
00611   {
00612     TimerObject *tmp = m_timer_object_queue;
00613 
00614     while (tmp)
00615     {
00616       if (tmp == timer_object.m_d && (tmp->uid == timer_object.m_d->uid))
00617       {
00618         return true;
00619       }
00620 
00621       tmp = tmp->next;
00622     }
00623 
00624     return false;
00625   }
00626 
00627 //----------------------------------------------------------------------------
00628   int TimerHandler::DelayUntilNextTimerExpires()
00629   {
00630     TimeStruct now;
00631     TimeStruct delay;
00632 
00633     if (m_timer_object_queue == NULL)
00634     {
00635       // The return value of this function is only valid if there _are_ timers active.
00636       return 0;
00637     }
00638     else
00639     {
00640       TimeRightNow(&now);
00641 
00642       if (TimeIsGreater(now, m_timer_object_queue->when))
00643       {
00644         return 0;
00645       }
00646       else
00647       {
00648         delay.sec = m_timer_object_queue->when.sec - now.sec;
00649         delay.usec = m_timer_object_queue->when.usec - now.usec;
00650 
00651         // make sure that usec cannot be less than -1000000 before applying this code
00652         if (delay.usec < 0)
00653         {
00654           delay.usec += 1000000;
00655           delay.sec--;
00656         }
00657 
00658         return  (delay.sec * 1000000 + delay.usec) / 1000; // return delay in milliseconds
00659       }
00660     }
00661   }
00662 
00663   /*unsigned int TimeDiff( TimeStruct t1, TimeStruct t2)
00664   {
00665       int sec;
00666       int usec;
00667       if (t1.sec >= t2.sec)
00668       {
00669           sec = t1.sec - t2.sec;
00670           usec = t1.usec - t2.usec;
00671           while ((usec < 0) && (sec > 0))
00672           {
00673               usec += 1000000;
00674               sec -= 1;
00675           }
00676           if (usec < 0)
00677               usec = -usec;
00678       }
00679 
00680       if (t1.sec < t2.sec)
00681       {
00682           sec = t2.sec - t1.sec;
00683           usec = t2.usec - t1.usec;
00684           while ((usec < 0) && (sec > 0))
00685           {
00686               usec += 1000000;
00687               sec -= 1;
00688           }
00689           if (usec < 0)
00690               usec = -usec;
00691       }
00692       return sec*1000 + usec/1000; // time diff is millisecond
00693   }*/
00694 
00695   bool TimeIsGreater( TimeStruct t1, TimeStruct t2)
00696   {
00697     if ((t1.sec > t2.sec) || ((t1.sec == t2.sec) && (t1.usec > t2.usec)))
00698       return true;
00699 
00700     if ((t1.sec == t2.sec) && (t1.usec == t2.usec))
00701       return true;
00702 
00703     return false;
00704   }
00705 
00706   void TimeRightNow(TimeStruct *tv)
00707   {
00708 #if defined(NUX_OS_WINDOWS)
00709     struct _timeb timebuffer;
00710     // Time in seconds since midnight(00:00:00), January 1, 1970, coordinated universal time(UTC).
00711     _ftime(&timebuffer);
00712     tv->sec = timebuffer.time;
00713     tv->usec = timebuffer.millitm * 1000;
00714 #elif defined(NUX_OS_LINUX)
00715     timeval unix_timeval;
00716     gettimeofday(&unix_timeval, NULL);
00717     tv->sec = unix_timeval.tv_sec;
00718     tv->usec = unix_timeval.tv_usec;
00719 #else
00720 #error TimeRightNow is not implemented for this platform.
00721 #endif
00722   }
00723 
00724   void Addmillisecs(TimeStruct *tv, unsigned int milliseconds)
00725   {
00726     tv->usec += milliseconds * 1000;
00727     tv->sec += tv->usec / 1000000;
00728     tv->usec = tv->usec % 1000000;
00729   }
00730 
00731 
00732 }