home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / generic / timer.cpp < prev    next >
C/C++ Source or Header  |  2002-11-09  |  7KB  |  236 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        mgl/timer.cpp
  3. // Purpose:     wxTimer implementation
  4. // Author:      Vaclav Slavik
  5. // Id:          $Id: timer.cpp,v 1.3.2.1 2002/11/09 15:20:36 RR Exp $
  6. // Copyright:   (c) 2001-2002 SciTech Software, Inc. (www.scitechsoft.com)
  7. // Licence:     wxWindows licence
  8. /////////////////////////////////////////////////////////////////////////////
  9.  
  10. #ifdef __GNUG__
  11. #pragma implementation "timer.h"
  12. #endif
  13.  
  14. // For compilers that support precompilation, includes "wx.h".
  15. #include "wx/wxprec.h"
  16.  
  17. #ifdef __BORLANDC__
  18.     #pragma hdrstop
  19. #endif
  20.  
  21. // ----------------------------------------------------------------------------
  22. // NB: when using generic wxTimer implementation in your port, you *must* call 
  23. //     wxTimer::NotifyTimers() often enough. The ideal place for this 
  24. //     is in wxEventLoop::Dispatch().
  25. // ----------------------------------------------------------------------------
  26.  
  27. #include "wx/timer.h"
  28.  
  29. #if wxUSE_TIMER
  30.  
  31. #include "wx/log.h"
  32. #include "wx/module.h"
  33.  
  34. // ----------------------------------------------------------------------------
  35. // Time input function
  36. // ----------------------------------------------------------------------------
  37.  
  38. #ifdef __WXMGL__
  39.     // We take advantage of wxMGL's _EVT_getTicks because it is faster
  40.     // (especially under MS-DOS!) and more precise than wxGetLocalTimeMillis
  41.     // if we are unlucky and the latter combines information from two sources.
  42.     #include "wx/mgl/private.h"
  43.     extern "C" ulong _EVT_getTicks();
  44.     #define GetMillisecondsTime() _EVT_getTicks()
  45. #else
  46. //    #define GetMillisecondsTime() wxGetLocalTimeMillis().ToLong()
  47.     // Suppresses the debug warning in ToLong. FIXME: check
  48.     // that we don't drastically lose precision
  49.     #define GetMillisecondsTime() (unsigned long) wxGetLocalTimeMillis().GetValue()
  50. #endif
  51.  
  52. // ----------------------------------------------------------------------------
  53. // helper structures and wxTimerScheduler
  54. // ----------------------------------------------------------------------------
  55.  
  56. class wxTimerDesc
  57. {
  58. public:
  59.     wxTimerDesc(wxTimer *t) : 
  60.         timer(t), running(FALSE), next(NULL), prev(NULL), 
  61.         shotTime(0), deleteFlag(NULL) {}
  62.  
  63.     wxTimer         *timer;
  64.     bool             running;
  65.     wxTimerDesc     *next, *prev;
  66.     unsigned long    shotTime;  
  67.     volatile bool   *deleteFlag; // see comment in ~wxTimer
  68. };
  69.  
  70. class wxTimerScheduler
  71. {
  72. public:
  73.     wxTimerScheduler() : m_timers(NULL) {}
  74.  
  75.     void QueueTimer(wxTimerDesc *desc, unsigned long when = 0);
  76.     void RemoveTimer(wxTimerDesc *desc);
  77.     void NotifyTimers();
  78.    
  79. private:
  80.     wxTimerDesc *m_timers;
  81. };
  82.  
  83. void wxTimerScheduler::QueueTimer(wxTimerDesc *desc, unsigned long when)
  84. {
  85.     if ( desc->running )
  86.         return; // already scheduled
  87.         
  88.     if ( when == 0 )
  89.         when = GetMillisecondsTime() + desc->timer->GetInterval();
  90.     desc->shotTime = when;
  91.     desc->running = TRUE;
  92.  
  93.     wxLogTrace( wxT("timer"), wxT("queued timer %p at tick %ld"), 
  94.                desc->timer, (long) when);
  95.  
  96.     if ( m_timers )
  97.     {
  98.         wxTimerDesc *d = m_timers;
  99.         while ( d->next && d->next->shotTime < when ) d = d->next;
  100.         desc->next = d->next;
  101.         desc->prev = d;
  102.         if ( d->next )
  103.             d->next->prev = desc;
  104.         d->next = desc;
  105.     }
  106.     else
  107.     {
  108.         m_timers = desc;
  109.         desc->prev = desc->next = NULL;
  110.     }
  111. }
  112.  
  113. void wxTimerScheduler::RemoveTimer(wxTimerDesc *desc)
  114. {
  115.     desc->running = FALSE;
  116.     if ( desc == m_timers )
  117.         m_timers = desc->next;
  118.     if ( desc->prev )
  119.         desc->prev->next = desc->next;
  120.     if ( desc->next )
  121.         desc->next->prev = desc->prev;
  122.     desc->prev = desc->next = NULL;
  123. }
  124.  
  125. void wxTimerScheduler::NotifyTimers()
  126. {
  127.     if ( m_timers )
  128.     {
  129.         bool oneShot;
  130.         volatile bool timerDeleted;
  131.         unsigned long now = GetMillisecondsTime();
  132.         wxTimerDesc *desc;
  133.  
  134.         while ( m_timers && m_timers->shotTime <= now )
  135.         {
  136.             desc = m_timers;
  137.             oneShot = desc->timer->IsOneShot();
  138.             RemoveTimer(desc);
  139.  
  140.             timerDeleted = FALSE;
  141.             desc->deleteFlag = &timerDeleted;
  142.             desc->timer->Notify();
  143.             
  144.             if ( !timerDeleted )
  145.             {
  146.                 wxLogTrace( wxT("timer"), wxT("notified timer %p sheduled for %ld"), 
  147.                            desc->timer, (long) desc->shotTime);
  148.  
  149.                 desc->deleteFlag = NULL;
  150.                 if ( !oneShot )
  151.                     QueueTimer(desc, now + desc->timer->GetInterval());
  152.             }
  153.         }
  154.     }
  155. }
  156.  
  157.  
  158. // ----------------------------------------------------------------------------
  159. // wxTimer
  160. // ----------------------------------------------------------------------------
  161.  
  162. IMPLEMENT_ABSTRACT_CLASS(wxTimer,wxObject)
  163.  
  164. wxTimerScheduler *gs_scheduler = NULL;
  165.  
  166. void wxTimer::Init()
  167. {
  168.     if ( !gs_scheduler )
  169.         gs_scheduler = new wxTimerScheduler;
  170.     m_desc = new wxTimerDesc(this);
  171. }
  172.  
  173. wxTimer::~wxTimer()
  174. {
  175.     wxLogTrace( wxT("timer"), wxT("destroying timer %p..."), this);
  176.     if ( IsRunning() )
  177.         Stop();
  178.  
  179.     // NB: this is a hack: wxTimerScheduler must have some way of knowing
  180.     //     that wxTimer object was deleted under its hands -- this may 
  181.     //     happen if somebody is really nasty and deletes the timer
  182.     //     from wxTimer::Notify()
  183.     if ( m_desc->deleteFlag != NULL )
  184.         *m_desc->deleteFlag = TRUE;
  185.  
  186.     delete m_desc;
  187.     wxLogTrace( wxT("timer"), wxT("    ...done destroying timer %p..."), this);
  188. }
  189.  
  190. bool wxTimer::IsRunning() const
  191. {
  192.     return m_desc->running;
  193. }
  194.  
  195. bool wxTimer::Start(int millisecs, bool oneShot)
  196. {
  197.     wxLogTrace( wxT("timer"), wxT("started timer %p: %i ms, oneshot=%i"), 
  198.                this, millisecs, oneShot);
  199.  
  200.     if ( !wxTimerBase::Start(millisecs, oneShot) )
  201.         return FALSE;
  202.     
  203.     gs_scheduler->QueueTimer(m_desc);
  204.     return TRUE;
  205. }
  206.  
  207. void wxTimer::Stop()
  208. {
  209.     if ( !m_desc->running ) return;
  210.     
  211.     gs_scheduler->RemoveTimer(m_desc);
  212. }
  213.  
  214. /*static*/ void wxTimer::NotifyTimers()
  215. {
  216.     if ( gs_scheduler )
  217.         gs_scheduler->NotifyTimers();
  218. }
  219.  
  220.  
  221.  
  222. // A module to deallocate memory properly:
  223. class wxTimerModule: public wxModule
  224. {
  225. DECLARE_DYNAMIC_CLASS(wxTimerModule)
  226. public:
  227.     wxTimerModule() {}
  228.     bool OnInit() { return TRUE; }
  229.     void OnExit() { delete gs_scheduler; gs_scheduler = NULL; }
  230. };
  231.  
  232. IMPLEMENT_DYNAMIC_CLASS(wxTimerModule, wxModule)
  233.  
  234.  
  235. #endif //wxUSE_TIMER
  236.