Back to index

nux  3.0.0
Public Types | Public Member Functions | Private Member Functions | Private Attributes
nux::TimerHandler Class Reference

A timer manager class created by WindowThread. More...

#include <TimerProc.h>

Collaboration diagram for nux::TimerHandler:
Collaboration graph
[legend]

List of all members.

Public Types

enum  { TIMERTYPE_UNKNONW = 0L, TIMERTYPE_PERIODIC, TIMERTYPE_DURATION, TIMERTYPE_ITERATION }

Public Member Functions

 TimerHandler (WindowThread *window_thread)
 ~TimerHandler ()
TimerHandle AddTimerHandler (unsigned int Period, TimeOutSignal *timeout_signal, void *Data, WindowThread *window_thread=NULL)
 Add a timer callback.
TimerHandle AddPeriodicTimerHandler (unsigned int Period, int Duration, TimeOutSignal *timeout_signal, void *Data)
 Add a periodic timer callback.
TimerHandle AddCountIterationTimerHandler (unsigned int Period, int NumberOfIteration, TimeOutSignal *timeout_signal, void *Data)
 Add a timer callback to be called a finite number of time.
bool FindTimerHandle (TimerHandle &handle)
 Search for a timer handle.
bool RemoveTimerHandler (TimerHandle &handle)
 Remove a timer;.
int DelayUntilNextTimerExpires ()
 Return the delay until the next timer expires.
int ExecTimerHandler ()
void StartEarlyTimerObjects ()
 Start the timers that were sett before the system was fully initialized.

Private Member Functions

TimerObjectAddHandle (TimerObject *handle)
unsigned int GetNumPendingHandler ()

Private Attributes

WindowThreadwindow_thread_
 The WindowThread to which this object belongs.
bool m_IsProceesingTimers
TimerObjectm_timer_object_queue
 Single linked list of timer delays.
std::list< TimerObject * > _early_timer_objects
 timer objects that couldn't be started because the main loop is not runing yet.

Detailed Description

A timer manager class created by WindowThread.

Definition at line 69 of file TimerProc.h.


Member Enumeration Documentation

anonymous enum
Enumerator:
TIMERTYPE_UNKNONW 
TIMERTYPE_PERIODIC 
TIMERTYPE_DURATION 
TIMERTYPE_ITERATION 

Definition at line 72 of file TimerProc.h.


Constructor & Destructor Documentation

Definition at line 169 of file TimerProc.cpp.

  : window_thread_(window_thread)
  {
    m_timer_object_queue = 0;
    m_IsProceesingTimers = false;
  }

Definition at line 176 of file TimerProc.cpp.

  {

  }

Member Function Documentation

TimerHandle nux::TimerHandler::AddCountIterationTimerHandler ( unsigned int  Period,
int  NumberOfIteration,
TimeOutSignal timeout_signal,
void *  Data 
)

Add a timer callback to be called a finite number of time.

Add a timer callback to the timer manager. The timer callback will be call N times exactly. Every time the timer expires, the callback function is executed. The returned TimerHandle should not be deleted by the caller.

Parameters:
MillisecondsPeriod delay before the callback is executed.
NumberOfIterationThe number of time to repeat the the wait period.
timeout_signalThe callback to execute when the timer expires.
DataThe callback data
Returns:
A handle to the timer.

Definition at line 272 of file TimerProc.cpp.

  {
    TimerObject *timer_object = new TimerObject();
    TimeRightNow(&timer_object->when);
    Addmillisecs(&timer_object->when, Period);
    timer_object->CallbackData = Data;
    timer_object->timeout_signal = timeout_signal;

    timer_object->Period = Period;
    timer_object->ScheduledIteration  = (NumberOfIterations < 0) ? -1 : NumberOfIterations;
    timer_object->Type = TIMERTYPE_ITERATION;
    AddHandle(timer_object);

#if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
    {
      timer_object->glibid = GetWindowThread()->AddTimeout(Period);

      if (timer_object->glibid == 0)
      {
        _early_timer_objects.push_back(timer_object);
        // Probably trying to set a timeout before Glib main context and loop have been created.
        // Sometimes later, this timer will be examined when ExecTimerHandler is called.
        // This happens when trying to set a callback before the mainloop has been initialized.
      }

      //nuxDebugMsg("[TimerHandler::AddTimerHandler] Adding Timeout ID: %d", timer_object->glibid);
    }
#endif
    TimerHandle handle(timer_object);
    return handle;
  }

Here is the call graph for this function:

Definition at line 305 of file TimerProc.cpp.

  {
    if (timer_object == NULL)
      return NULL;

    // Give the Timer a unique ID;
    timer_object->uid = TimerUID.GetValue();
    TimerUID.Increment();

    // If the queue is empty or the new timer will expire sooner than the first timer in the queue
    // then add the new timer at the start of the queue.
    if ((m_timer_object_queue == NULL) || TimeIsGreater(m_timer_object_queue->when, timer_object->when))
    {
      // Add the timer timer_object at the head of the queue
      timer_object->next = m_timer_object_queue;

      if (m_timer_object_queue)
        m_timer_object_queue->prev = timer_object;

      timer_object->prev = 0;
      m_timer_object_queue = timer_object;

      return timer_object;
    }

    TimerObject *tmp = m_timer_object_queue;

    while (tmp->next != NULL)
    {
      // Is the time to wait for tmp->next to expire smaller than for timer_object
      if (TimeIsGreater(timer_object->when, tmp->next->when))
      {
        // keep searching
        tmp = tmp->next;
      }
      else
      {
        timer_object->next = tmp->next;
        tmp->next->prev = timer_object;
        tmp->next = timer_object;
        timer_object->prev = tmp;
        return timer_object;
      }
    }

    tmp->next = timer_object;
    timer_object->next = NULL;
    timer_object->prev = tmp;
    return timer_object;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

TimerHandle nux::TimerHandler::AddPeriodicTimerHandler ( unsigned int  Period,
int  Duration,
TimeOutSignal timeout_signal,
void *  Data 
)

Add a periodic timer callback.

Add a timer callback to the timer manager. Every time the timer expires, the callback function is executed. The returned TimerHandle should not be deleted by the caller.

Parameters:
MillisecondsPeriod delay before the callback is executed.
DurationThe duration over which the timer is repeated.
timeout_signalThe callback to execute when the timer expires.
DataThe callback data
Returns:
A handle to the timer.

Definition at line 239 of file TimerProc.cpp.

  {
    TimerObject *timer_object = new TimerObject();
    TimeRightNow(&timer_object->when);
    Addmillisecs(&timer_object->when, Period);
    timer_object->CallbackData = Data;
    timer_object->timeout_signal = timeout_signal;

    timer_object->Period = Period;
    timer_object->Duration = (Duration < 0) ? -1 : Duration;
    timer_object->Type = TIMERTYPE_DURATION;
    AddHandle(timer_object);

#if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
    {
      timer_object->glibid = GetWindowThread()->AddTimeout(Period);

      if (timer_object->glibid == 0)
      {
        _early_timer_objects.push_back(timer_object);
        // Probably trying to set a timeout before Glib main context and loop have been created.
        // Sometimes later, this timer will be examined when ExecTimerHandler is called.
        // This happens when trying to set a callback before the mainloop has been initialized.
      }

      //nuxDebugMsg("[TimerHandler::AddTimerHandler] Adding Timeout ID: %d", timer_object->glibid);
    }
#endif

    TimerHandle handle(timer_object);
    return handle;
  }

Here is the call graph for this function:

TimerHandle nux::TimerHandler::AddTimerHandler ( unsigned int  Period,
TimeOutSignal timeout_signal,
void *  Data,
WindowThread window_thread = NULL 
)

Add a timer callback.

Add a timer callback to the timer manager. When the timer expires, the callback function is executed. The returned TimerObject should not be deleted by the caller.

Parameters:
MillisecondsPeriod delay before the callback is executed.
timeout_signalThe callback to execute when the timer expires.
DataThe callback data
window_threadThread safety mesure. Pass the WindowThread associated to this TimerHandler if it is called from a different thread than the one where the main thread was created.
Returns:
A handle to the timer.

Definition at line 198 of file TimerProc.cpp.

  {
    TimerObject *timer_object = new TimerObject();

    TimeRightNow(&timer_object->when);
    Addmillisecs(&timer_object->when, Period);

    timer_object->CallbackData  = Data;
    timer_object->timeout_signal = timeout_signal;
    timer_object->Period        = Period;
    timer_object->Type          = TIMERTYPE_PERIODIC;
    if (window_thread)
      timer_object->Window        = window_thread->GetWindowCompositor().GetProcessingTopView();
    else
      timer_object->Window        = GetWindowThread()->GetWindowCompositor().GetProcessingTopView();
    
    AddHandle(timer_object);

#if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
    {
      if (window_thread)
        timer_object->glibid = window_thread->AddTimeout(Period);
      else
        timer_object->glibid = GetWindowThread()->AddTimeout(Period);
      
      if (timer_object->glibid == 0)
      {
        _early_timer_objects.push_back(timer_object);
        // Probably trying to set a timeout before Glib main context and loop have been created.
        // Sometimes later, this timer will be examined when ExecTimerHandler is called.
        // This happens when trying to set a callback before the mainloop has been initialized.
      }

      //nuxDebugMsg("[TimerHandler::AddTimerHandler] Adding Timeout ID: %d", timer_object->glibid);
    }
#endif

    TimerHandle handle(timer_object);
    return handle;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Return the delay until the next timer expires.

Returns:
Delay to next timer expiration in milliseconds.

Definition at line 628 of file TimerProc.cpp.

  {
    TimeStruct now;
    TimeStruct delay;

    if (m_timer_object_queue == NULL)
    {
      // The return value of this function is only valid if there _are_ timers active.
      return 0;
    }
    else
    {
      TimeRightNow(&now);

      if (TimeIsGreater(now, m_timer_object_queue->when))
      {
        return 0;
      }
      else
      {
        delay.sec = m_timer_object_queue->when.sec - now.sec;
        delay.usec = m_timer_object_queue->when.usec - now.usec;

        // make sure that usec cannot be less than -1000000 before applying this code
        if (delay.usec < 0)
        {
          delay.usec += 1000000;
          delay.sec--;
        }

        return  (delay.sec * 1000000 + delay.usec) / 1000; // return delay in milliseconds
      }
    }
  }

Here is the call graph for this function:

Definition at line 411 of file TimerProc.cpp.

  {
    NUX_RETURN_VALUE_IF_NULL(m_timer_object_queue, 0);

    bool repeat = false;
    TimerObject *timer_object = m_timer_object_queue;
    TimeStruct now;

    int timer_executed = 0;

    TimeRightNow(&now);

    m_IsProceesingTimers = true;

    while (timer_object != NULL)
    {
#if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))

      if ((/*TimeIsGreater(now, timer_object->when) ||*/ (timer_object->glibid == timer_id)) && (timer_object->MarkedForRemoval == false))
#else
      if (TimeIsGreater(now, timer_object->when))
#endif
      {
        long elaps = now.sec - timer_object->when.sec;
        long uelaps = now.usec - timer_object->when.usec;

        if (uelaps < 0)
        {
          uelaps += 1000000;
          //nuxAssert(elaps > 0);
          elaps -= 1;
        }

        timer_object->ElapsedTime += timer_object->Period; //elaps * 1000 + uelaps / 1000; // milliseconds

        if (timer_object->Type == TIMERTYPE_PERIODIC)
        {
          timer_object->ProgressDelta = float(timer_object->ElapsedTime) / float(timer_object->Period) - timer_object->Param;
          // Clamp progress delta so(timer_object->Param + timer_object->ProgressDelta) <= 1.0f
          if (timer_object->Param + timer_object->ProgressDelta > 1.0f)
            timer_object->ProgressDelta = 1.0f - timer_object->Param;

          timer_object->Param = float(timer_object->ElapsedTime) / float(timer_object->Period);
        }
        else if (timer_object->Type == TIMERTYPE_DURATION)
        {
          timer_object->ProgressDelta = float(timer_object->ElapsedTime) / float(timer_object->Duration) - timer_object->Param;
          // Clamp progress delta so(timer_object->Param + timer_object->ProgressDelta) <= 1.0f
          if (timer_object->Param + timer_object->ProgressDelta > 1.0f)
            timer_object->ProgressDelta = 1.0f - timer_object->Param;

          if (timer_object->ProgressDelta < 0.0f)
            timer_object->ProgressDelta = 0.0f;

          timer_object->Param = float(timer_object->ElapsedTime) / float(timer_object->Duration);
        }
        else if (timer_object->Type == TIMERTYPE_ITERATION)
        {
          timer_object->ProgressIterationCount += 1;
          int duration = timer_object->Period * timer_object->ScheduledIteration;

          timer_object->ProgressDelta = float(timer_object->ElapsedTime) / float(duration) - timer_object->Param;
          // Clamp progress delta so(timer_object->Param + timer_object->ProgressDelta) <= 1.0f
          if (timer_object->Param + timer_object->ProgressDelta > 1.0f)
            timer_object->ProgressDelta = 1.0f - timer_object->Param;

          timer_object->Param = float(timer_object->ElapsedTime) / float(duration);
        }
        else
        {
          nuxAssertMsg(0, "[TimerHandler::ExecTimerHandler] Unknown timer type.");
        }

        if (timer_object->Param > 1.0f)
          timer_object->Param = 1.0f;

        timer_object->MarkedForRemoval = false;

        if (timer_object->timeout_signal != 0)
        {
          GetWindowThread()->GetWindowCompositor().SetProcessingTopView(timer_object->Window);
          timer_object->timeout_signal->time_expires.emit(timer_object->CallbackData);
          GetWindowThread()->GetWindowCompositor().SetProcessingTopView(NULL);          
          // Reset glibid to 0. glibid is not null, if this element ever happened to be at the head of the queue
          // and we set a timer for it.
          //nuxDebugMsg("[TimerHandler::ExecTimerHandler] Executed Timeout ID: %d", timer_object->glibid);
          //timer_object->glibid = 0;
        }

        TimerObject *expired_handler = 0;

        if (timer_object->MarkedForRemoval)
        {
          // RemoveTimerHandler was called during the callback execution
          expired_handler = timer_object;
        }
        else if (timer_object->Type == TIMERTYPE_PERIODIC)
        {
          expired_handler = timer_object;
        }
        else if ((timer_object->Type == TIMERTYPE_DURATION) && (timer_object->Param >= 1.0f))
        {
          expired_handler = timer_object;
        }
        else if ((timer_object->Type == TIMERTYPE_ITERATION) && (timer_object->ProgressIterationCount >= timer_object->ScheduledIteration))
        {
          expired_handler = timer_object;
        }

        if (expired_handler)
        {
          if (timer_object->next)
            timer_object->next->prev = timer_object->prev;

          if (timer_object->prev)
            timer_object->prev->next = timer_object->next;

          if ((timer_object == m_timer_object_queue) && (timer_object->uid == m_timer_object_queue->uid))
          {
            // timer_object is the first element of the queue.
            m_timer_object_queue = timer_object->next;

            if (m_timer_object_queue)
            {
              m_timer_object_queue->prev = 0;
            }
          }

          timer_object = timer_object->next;

          delete expired_handler;
        }
        else
        {
          repeat = true;
          //timer_object = timer_object->next;
        }

        timer_executed++;
        break;
      }
      else
      {
        timer_object = timer_object->next;
      }
    }

//     // Look at the head of the queue and set a glib timeout for the first element, if one wasn't set already.
//     if (m_timer_object_queue && (m_timer_object_queue->glibid == 0))
//     {
//         // How long(in milliseconds) between now and the moment the timeout expires?
//         unsigned int time_difference = TimeDiff(now, m_timer_object_queue->when);
//
//         m_timer_object_queue->glibid = GetWindowThread()->AddTimeout(time_difference);
//         //nuxDebugMsg("[TimerHandler::ExecTimerHandler] Adding Timeout ID: %d", m_timer_object_queue->glibid);
//     }

    // Purge handles that have been marked for removal
    timer_object = m_timer_object_queue;

    while (timer_object)
    {
      if (timer_object->MarkedForRemoval)
      {
        TimerObject *expired_handler = timer_object;

        if (timer_object->next)
          timer_object->next->prev = timer_object->prev;

        if (timer_object->prev)
          timer_object->prev->next = timer_object->next;
        else
        {
          // timer_object is the first element of the queue.
          m_timer_object_queue = timer_object->next;

          if (m_timer_object_queue)
          {
            m_timer_object_queue->prev = 0;
          }
        }

        timer_object = timer_object->next;
        delete expired_handler;
      }
      else
      {
        timer_object = timer_object->next;
      }
    }

    m_IsProceesingTimers = false;
    //return timer_executed;
    return repeat;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

Search for a timer handle.

Search for a timer handle in the timer handle queue. Return true if the timer is found.

Parameters:
handleTimer handle to search.
Returns:
Return true if the timer is found; false otherwise.

Definition at line 610 of file TimerProc.cpp.

  {
    TimerObject *tmp = m_timer_object_queue;

    while (tmp)
    {
      if (tmp == timer_object.m_d && (tmp->uid == timer_object.m_d->uid))
      {
        return true;
      }

      tmp = tmp->next;
    }

    return false;
  }
unsigned int nux::TimerHandler::GetNumPendingHandler ( ) [private]

Definition at line 356 of file TimerProc.cpp.

  {
    unsigned int count = 0;
    TimerObject *head = m_timer_object_queue;

    while (head)
    {
      count++;
      head = head->next;
    }

    return count;
  }

Remove a timer;.

Parameters:
handleTimer handle to search.
Returns:
Return True if the timer is found.

Definition at line 370 of file TimerProc.cpp.

  {
    NUX_RETURN_VALUE_IF_NULL(timer_object.m_d, false);
    NUX_RETURN_VALUE_IF_NULL(m_timer_object_queue, false);

    TimerObject *tmp;

    tmp = m_timer_object_queue;

    while (tmp)
    {
      if ((tmp == timer_object.m_d) && (tmp->uid == timer_object.m_d->uid))
      {
        if (!m_IsProceesingTimers)
        {
          if (tmp->next)
            tmp->next->prev = tmp->prev;

          if (tmp->prev)
            tmp->prev->next = tmp->next;

          if ((timer_object.m_d == m_timer_object_queue) && (timer_object.m_d->uid == m_timer_object_queue->uid))
            m_timer_object_queue = timer_object.m_d->next;

          NUX_SAFE_DELETE(timer_object.m_d);
        }
        else
        {
          timer_object.m_d->MarkedForRemoval = true;
        }

        return true;
      }

      tmp = tmp->next;
    }

    return false;
  }

Here is the caller graph for this function:

Start the timers that were sett before the system was fully initialized.

Definition at line 181 of file TimerProc.cpp.

  {
    std::list<TimerObject*>::iterator it;
    for (it = _early_timer_objects.begin(); it != _early_timer_objects.end(); it++)
    {
      TimerObject *timer_object = *it;
      TimeRightNow(&timer_object->when);
      Addmillisecs(&timer_object->when, timer_object->Period);

#if (defined(NUX_OS_LINUX) || defined(NUX_USE_GLIB_LOOP_ON_WINDOWS)) && (!defined(NUX_DISABLE_GLIB_LOOP))
        timer_object->glibid = GetWindowThread()->AddTimeout(timer_object->Period);
#endif
    }

    _early_timer_objects.clear();
  }

Here is the call graph for this function:

Here is the caller graph for this function:


Member Data Documentation

timer objects that couldn't be started because the main loop is not runing yet.

Definition at line 161 of file TimerProc.h.

Definition at line 155 of file TimerProc.h.

Single linked list of timer delays.

Definition at line 160 of file TimerProc.h.

The WindowThread to which this object belongs.

Definition at line 153 of file TimerProc.h.


The documentation for this class was generated from the following files: