Logo Search packages:      
Sourcecode: scala version File versions  Download package

void scala::actors::FJTaskRunner::scan ( final FJTask  waitingFor  )  [inline, protected]

Do all but the pop() part of yield or join, by traversing all DEQs in our group looking for a task to steal. If none, it checks the entry queue.

Since there are no good, portable alternatives, we rely here on a mixture of Thread.yield and priorities to reduce wasted spinning, even though these are not well defined. We are hoping here that the JVM does something sensible.

Parameters:
waitingFor if non-null, the current task being joined

Definition at line 645 of file FJTaskRunner.java.

References COLLECT_STATS, scala::actors::IFJTaskRunnerGroup::getArray(), group, scala::actors::FJTask::isDone(), scala::actors::IFJTaskRunnerGroup::pollEntryQueue(), runPriority, runs, scanPriority, scans, scala::actors::FJTask::setDone(), steals, take(), and victimRNG.

Referenced by coInvoke(), taskJoin(), and taskYield().

                                               {

    FJTask task = null;

    // to delay lowering priority until first failure to steal
    boolean lowered = false;
    
    /*
      Circularly traverse from a random start index. 
      
      This differs slightly from cilk version that uses a random index
      for each attempted steal.
      Exhaustive scanning might impede analytic tractablity of 
      the scheduling policy, but makes it much easier to deal with
      startup and shutdown.
    */
    
    FJTaskRunner[] ts = group.getArray();
    int idx = victimRNG.nextInt(ts.length);
    
    for (int i = 0; i < ts.length; ++i) {
      
      FJTaskRunner t = ts[idx];
      if (++idx >= ts.length) idx = 0; // circularly traverse
      
      if (t != null && t != this) {
        
        if (waitingFor != null && waitingFor.isDone()) {
          break;
        }
        else {
          if (COLLECT_STATS) ++scans;
          task = t.take();
          if (task != null) {
            if (COLLECT_STATS) ++steals;
            break;
          }
          else if (isInterrupted()) {
            break;
          }
          else if (!lowered) { // if this is first fail, lower priority
            lowered = true;
            setPriority(scanPriority);
          }
          else {           // otherwise we are at low priority; just yield
            yield();
          }
        }
      }
      
    } 

    if (task == null) {
      if (COLLECT_STATS) ++scans;
      task = group.pollEntryQueue();
      if (COLLECT_STATS) if (task != null) ++steals;
    }
    
    if (lowered) setPriority(runPriority);
    
    if (task != null && !task.isDone()) {
      if (COLLECT_STATS) ++runs;
      task.run(); 
      task.setDone(); 
    }

  }


Generated by  Doxygen 1.6.0   Back to index