"Fossies" - the Fresh Open Source Software Archive

Member "muscle/util/PulseNode.cpp" (21 Nov 2020, 6677 Bytes) of package /linux/privat/muscle7.62.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "PulseNode.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 7.61_vs_7.62.

    1 /* This file is Copyright 2000-2013 Meyer Sound Laboratories Inc.  See the included LICENSE.txt file for details. */
    2 
    3 #include "util/PulseNode.h"
    4 
    5 namespace muscle {
    6 
    7 PulseNode :: PulseNode()
    8    : _parent(NULL)
    9    , _aggregatePulseTime(MUSCLE_TIME_NEVER)
   10    , _myScheduledTime(MUSCLE_TIME_NEVER)
   11    , _cycleStartedAt(0)
   12    , _myScheduledTimeValid(false)
   13    , _curList(-1)
   14    , _prevSibling(NULL)
   15    , _nextSibling(NULL)
   16    , _maxTimeSlice(MUSCLE_TIME_NEVER)
   17    , _timeSlicingSuggested(false)
   18 {
   19    for (uint32 i=0; i<NUM_LINKED_LISTS; i++) _firstChild[i] = _lastChild[i] = NULL;
   20 }
   21 
   22 PulseNode :: ~PulseNode() 
   23 {
   24    // unlink everybody, but don't delete anyone; no ownership is implied here!
   25    if (_parent) _parent->RemovePulseChild(this);
   26    ClearPulseChildren();
   27 }
   28 
   29 uint64 PulseNode :: GetPulseTime(const PulseArgs &) 
   30 {
   31    return MUSCLE_TIME_NEVER;
   32 }
   33 
   34 void PulseNode :: Pulse(const PulseArgs &) 
   35 {
   36    // empty
   37 }
   38 
   39 void PulseNode :: InvalidatePulseTime(bool clearPrevResult)
   40 {
   41    if (_myScheduledTimeValid)
   42    {
   43       _myScheduledTimeValid = false;
   44       if (clearPrevResult) _myScheduledTime = MUSCLE_TIME_NEVER;
   45       if (_parent) _parent->ReschedulePulseChild(this, LINKED_LIST_NEEDSRECALC);
   46    }
   47 }
   48 
   49 void PulseNode :: GetPulseTimeAux(uint64 now, uint64 & min)
   50 {
   51    // First, update myself, if necessary...
   52    if (_myScheduledTimeValid == false) 
   53    {
   54       _myScheduledTimeValid = true;
   55       _myScheduledTime = GetPulseTime(PulseArgs(now, _myScheduledTime));
   56    }
   57 
   58    // Then handle any of my kids who need to be recalculated also
   59    PulseNode * & firstNeedy = _firstChild[LINKED_LIST_NEEDSRECALC];
   60    if (firstNeedy) while(firstNeedy) firstNeedy->GetPulseTimeAux(now, min);  // guaranteed to move (firstNeedy) out of the recalc list!
   61 
   62    // Recalculate our effective pulse time
   63    const uint64 oldAggregatePulseTime = _aggregatePulseTime;
   64    _aggregatePulseTime = muscleMin(_myScheduledTime, GetFirstScheduledChildTime());
   65    if ((_parent)&&((_curList == LINKED_LIST_NEEDSRECALC)||(_aggregatePulseTime != oldAggregatePulseTime))) _parent->ReschedulePulseChild(this, (_aggregatePulseTime==MUSCLE_TIME_NEVER)?LINKED_LIST_UNSCHEDULED:LINKED_LIST_SCHEDULED);
   66 
   67    // Update the caller's minimum time value
   68    if (_aggregatePulseTime < min) min = _aggregatePulseTime;
   69 }
   70 
   71 void PulseNode :: PulseAux(uint64 now)
   72 {
   73    if ((_myScheduledTimeValid)&&(now >= _myScheduledTime)) 
   74    {
   75       Pulse(PulseArgs(now, _myScheduledTime));
   76       _myScheduledTimeValid = false;
   77    }
   78 
   79    PulseNode * p = _firstChild[LINKED_LIST_SCHEDULED];
   80    while((p)&&(now >= p->_aggregatePulseTime))
   81    {
   82       p->PulseAux(now);  // guaranteed to move (p) to our NEEDSRECALC list
   83       p = _firstChild[LINKED_LIST_SCHEDULED];  // and move on to the next scheduled child
   84    }
   85 
   86    // Make sure we get recalculated no matter what (because we know something happened)
   87    if (_parent) _parent->ReschedulePulseChild(this, LINKED_LIST_NEEDSRECALC);
   88 }
   89 
   90 status_t PulseNode :: PutPulseChild(PulseNode * child)
   91 {
   92    if (child->_parent) child->_parent->RemovePulseChild(child);
   93    child->_parent = this;
   94    ReschedulePulseChild(child, LINKED_LIST_NEEDSRECALC);
   95    return B_NO_ERROR;
   96 }
   97 
   98 status_t PulseNode :: RemovePulseChild(PulseNode * child)
   99 {
  100    if (child->_parent == this)
  101    {
  102       const bool doResched = (child == _firstChild[LINKED_LIST_SCHEDULED]);
  103       ReschedulePulseChild(child, -1);
  104       child->_parent = NULL;
  105       child->_myScheduledTimeValid = false;
  106       if ((doResched)&&(_parent)) _parent->ReschedulePulseChild(this, LINKED_LIST_NEEDSRECALC);
  107       return B_NO_ERROR;
  108    }
  109    else return B_BAD_ARGUMENT;
  110 }
  111 
  112 void PulseNode :: ClearPulseChildren()
  113 {
  114    for (uint32 i=0; i<NUM_LINKED_LISTS; i++) while(_firstChild[i]) (void) RemovePulseChild(_firstChild[i]);
  115 }
  116 
  117 void PulseNode :: ReschedulePulseChild(PulseNode * child, int whichList)
  118 {
  119    const int cl = child->_curList;
  120    if ((whichList != cl)||(cl == LINKED_LIST_SCHEDULED))  // since we may need to move within the scheduled list
  121    {
  122       // First, remove the child from any list he may currently be in
  123       if (cl >= 0)
  124       {
  125          if (child->_prevSibling) child->_prevSibling->_nextSibling = child->_nextSibling;
  126          if (child->_nextSibling) child->_nextSibling->_prevSibling = child->_prevSibling;
  127          if (child == _firstChild[cl]) _firstChild[cl] = child->_nextSibling;
  128          if (child == _lastChild[cl])  _lastChild[cl]  = child->_prevSibling;
  129          child->_prevSibling = child->_nextSibling = NULL;
  130       }
  131 
  132       child->_curList = whichList;
  133       switch(whichList)
  134       {
  135          case LINKED_LIST_SCHEDULED:
  136          {
  137             PulseNode * p = _firstChild[whichList];
  138             if (p)
  139             {
  140                PulseNode * lastChild = _lastChild[whichList];  // checking this for non-NULL solely to keep ClangSA happy --jaf
  141                if ((lastChild)&&(child->_aggregatePulseTime >= lastChild->_aggregatePulseTime))
  142                {
  143                   // Shortcut:  append to the tail of the list!
  144                   child->_prevSibling = lastChild;
  145                   lastChild->_nextSibling = child;
  146                   _lastChild[whichList] = child;
  147                }
  148                else
  149                {
  150                   // Worst case:  O(N) walk through the list to find the place to insert (child)
  151                   while(p->_aggregatePulseTime < child->_aggregatePulseTime) p = p->_nextSibling;
  152 
  153                   // insert (child) just before (p)
  154                   child->_nextSibling = p;
  155                   child->_prevSibling = p->_prevSibling;
  156                   if (p->_prevSibling) p->_prevSibling->_nextSibling = child;
  157                                   else _firstChild[whichList] = child;  // FogBugz #4092(b)
  158                   p->_prevSibling = child;
  159                }
  160             }
  161             else _firstChild[whichList] = _lastChild[whichList] = child;
  162          }
  163          break;
  164 
  165          case LINKED_LIST_NEEDSRECALC:
  166             if (_parent) _parent->ReschedulePulseChild(this, LINKED_LIST_NEEDSRECALC);  // if our child is rescheduled that reschedules us too!
  167          // fall through!
  168          case LINKED_LIST_UNSCHEDULED: 
  169          {
  170             // These lists are unsorted, so we can just quickly prepend the child to the head of the list
  171             if (_firstChild[whichList])
  172             {
  173                child->_nextSibling = _firstChild[whichList];
  174                _firstChild[whichList]->_prevSibling = child;
  175                _firstChild[whichList] = child;
  176             }
  177             else _firstChild[whichList] = _lastChild[whichList] = child;
  178          }
  179          break;
  180 
  181          default:
  182             // do nothing
  183          break;
  184       }
  185    }
  186 }
  187 
  188 } // end namespace muscle