Ejemplo n.º 1
0
  public int executeFrame() {
    // printf("EXEC BEGIN\n");
    //
    // Run one frame. This takes the time stamp marking the end of the frame
    // and then processes events for that frame retroactively. This method
    // has
    // the advantage of flexibility, especially if the frame rate
    // fluctuates.
    // However it is always a little behind, because it can't compute the
    // frame length until the end of the frame is reached. With a fixed
    // known
    // frame rate you could optimize things a bit and make the start/end
    // times
    // correspond exactly with real time.
    //
    m_clock.beginFrame();
    // long started = m_clock.GetSystem();

    //
    // Execute any time-based tasks
    //
    // (1) Pop the next task off the list. Since the list is always
    // sorted, the first item in the list is always the next task.
    // (2) Execute it and update times
    // (3) If it's expired, delete it
    // Otherwise, insert it into the list in its new position
    //
    TaskInfo pTaskInfo = null;
    TaskInfo save = m_pTaskList;
    pTaskInfo = getNextTimeTask(pTaskInfo);
    while (pTaskInfo != null) {
      m_clock.advanceTo(pTaskInfo.time.next);

      pTaskInfo.pTask.execute(pTaskInfo.id, m_clock.getTime(), pTaskInfo.pUser);
      pTaskInfo.time.last = pTaskInfo.time.next;
      pTaskInfo.time.next += pTaskInfo.time.period;
      pTaskInfo = getNextTimeTask(pTaskInfo);
    }
    m_pTaskList = save;
    pTaskInfo = m_pTaskList;
    while (pTaskInfo != null) {

      if (pTaskInfo.time.duration == 0 || pTaskInfo.time.duration >= pTaskInfo.time.next) {
        // re-insert into list with updated time
        // InsertTimeTask(pTaskInfo);
      } else {
        // task is expired, delete it
        // printf("Sched: Expired %d\n",pTaskInfo->id);
        // delete pTaskInfo;
        terminate(pTaskInfo.id);
      }
      pTaskInfo = pTaskInfo.pNext;
    }

    //
    // Advance simulation clock to end of frame
    //
    m_clock.advanceToEnd();

    //
    // Now execute all frame tasks in round-robin fashion.
    // Frame tasks always execute at the end of the frame just
    // before rendering. A priority scheme could be used to
    // control sequence. It would be more efficient to keep the
    // list sorted, the same as with time tasks (exe
    //
    save = m_pFrameList;
    pTaskInfo = m_pFrameList;
    pTaskInfo = getNextFrameTask(pTaskInfo);
    // TaskInfo * pPrev = NULL;
    while (pTaskInfo != null) {
      pTaskInfo.pTask.execute(pTaskInfo.id, m_clock.getFrame(), pTaskInfo.pUser);
      pTaskInfo.time.last = pTaskInfo.time.next;
      pTaskInfo.time.next += pTaskInfo.time.period;
      pTaskInfo = getNextFrameTask(pTaskInfo);
    }
    m_pFrameList = save;
    // 检测是否有到期的任务
    pTaskInfo = m_pFrameList;
    while (pTaskInfo != null) {
      if (pTaskInfo.time.duration == 0 || pTaskInfo.time.duration >= pTaskInfo.time.next) {
        // re-insert into list with updated time
        // InsertFrameTask(pTaskInfo);
      } else {
        // task is expired, delete it
        // printf("Sched: Expired %d\n",pTaskInfo->id);
        // delete pTaskInfo;
        terminate(pTaskInfo.id);
      }
      pTaskInfo = pTaskInfo.pNext;
    }
    m_pFrameList = save;
    //
    // render
    //
    if (renderTask.pTask != null) {
      renderTask.pTask.execute(renderTask.id, m_clock.getFrame(), renderTask.pUser);
    }

    //
    // here is where we could do idle processing or load balancing
    //
    // long elapsed = m_clock.GetSystem() - started;
    // long frameLength = m_clock.GetFrameEnd() - m_clock.GetFrameStart();
    // printf("Busy %u ms, idle %u ms\n", elapsed, frameLength - elapsed);

    //
    // If any tasks are terminated during execution, it is easier to leave
    // them in the list until we're finished iterating through it, then
    // sweep
    // them out later.
    //
    // printf("EXEC END\n");
    for (Long i : queue) {
      terminate(i);
    }
    sweepGarbage();
    return 0;
  }