Beispiel #1
0
void MovingDots::updateDots() {
    //
    // Update positions
    //
    
    const GLint numValidDots = std::min(previousNumDots, currentNumDots);
    const GLfloat dt = GLfloat(currentTime - previousTime) / 1.0e6f;
    const GLfloat dr = dt * previousSpeed / previousFieldRadius;
    
    for (GLint i = 0; i < numValidDots; i++) {
        GLfloat &age = getAge(i);
        age += dt;
        
        if ((age <= previousLifetime) || (previousLifetime == 0.0f)) {
            advanceDot(i, dt, dr);
        } else {
            replaceDot(i, newDirection(previousCoherence), 0.0f);
        }
    }
    
    //
    // Update directions
    //
    
    if (currentCoherence != previousCoherence) {
        for (GLint i = 0; i < numValidDots; i++) {
            getDirection(i) = newDirection(currentCoherence);
        }
    }
    
    //
    // Update lifetimes
    //
    
    if (currentLifetime != previousLifetime) {
        for (GLint i = 0; i < numValidDots; i++) {
            getAge(i) = newAge(currentLifetime);
        }
    }
    
    //
    // Add/remove dots
    //
    
    if (currentNumDots != previousNumDots) {
        dotPositions.resize(currentNumDots * componentsPerDot);
        dotDirections.resize(currentNumDots);
        dotAges.resize(currentNumDots);
        
        for (GLint i = previousNumDots; i < currentNumDots; i++) {
            replaceDot(i, newDirection(currentCoherence), newAge(currentLifetime));
        }
    }
}
Beispiel #2
0
bool GenericTaskQueue<E, F, N>::pop_global(volatile E& t) {
  Age oldAge = _age.get();
  // Architectures with weak memory model require a barrier here
  // to guarantee that bottom is not older than age,
  // which is crucial for the correctness of the algorithm.
#if !(defined SPARC || defined IA32 || defined AMD64)
  OrderAccess::fence();
#endif
  uint localBot = OrderAccess::load_acquire((volatile juint*)&_bottom);
  uint n_elems = size(localBot, oldAge.top());
  if (n_elems == 0) {
    return false;
  }

  // g++ complains if the volatile result of the assignment is
  // unused, so we cast the volatile away.  We cannot cast directly
  // to void, because gcc treats that as not using the result of the
  // assignment.  However, casting to E& means that we trigger an
  // unused-value warning.  So, we cast the E& to void.
  (void) const_cast<E&>(t = _elems[oldAge.top()]);
  Age newAge(oldAge);
  newAge.increment();
  Age resAge = _age.cmpxchg(newAge, oldAge);

  // Note that using "_bottom" here might fail, since a pop_local might
  // have decremented it.
  assert(dirty_size(localBot, newAge.top()) != N - 1, "sanity");
  return resAge == oldAge;
}
Beispiel #3
0
bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
  // This queue was observed to contain exactly one element; either this
  // thread will claim it, or a competing "pop_global".  In either case,
  // the queue will be logically empty afterwards.  Create a new Age value
  // that represents the empty queue for the given value of "_bottom".  (We
  // must also increment "tag" because of the case where "bottom == 1",
  // "top == 0".  A pop_global could read the queue element in that case,
  // then have the owner thread do a pop followed by another push.  Without
  // the incrementing of "tag", the pop_global's CAS could succeed,
  // allowing it to believe it has claimed the stale element.)
  Age newAge((idx_t)localBot, oldAge.tag() + 1);
  // Perhaps a competing pop_global has already incremented "top", in which
  // case it wins the element.
  if (localBot == oldAge.top()) {
    // No competing pop_global has yet incremented "top"; we'll try to
    // install new_age, thus claiming the element.
    Age tempAge = _age.cmpxchg(newAge, oldAge);
    if (tempAge == oldAge) {
      // We win.
      assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
      TASKQUEUE_STATS_ONLY(stats.record_pop_slow());
      return true;
    }
  }
  // We lose; a completing pop_global gets the element.  But the queue is empty
  // and top is greater than bottom.  Fix this representation of the empty queue
  // to become the canonical one.
  _age.set(newAge);
  assert(dirty_size(localBot, _age.top()) != N - 1, "sanity");
  return false;
}
Beispiel #4
0
void MovingDots::advanceDot(GLint i, GLfloat dt, GLfloat dr) {
    GLfloat &x = getX(i);
    GLfloat &y = getY(i);
    GLfloat &theta = getDirection(i);
    
    x += dr * std::cos(theta);
    y += dr * std::sin(theta);
    
    if (x*x + y*y > 1.0f) {
        theta = newDirection(previousCoherence);
        
        GLfloat y1 = rand(-1.0f, 1.0f);
        GLfloat x1 = -std::sqrt(1.0f - y1*y1) + rand(0.0f, dr);
        
        x = x1*std::cos(theta) - y1*std::sin(theta);
        y = x1*std::sin(theta) + y1*std::cos(theta);
        
        getAge(i) = newAge(previousLifetime);
    }
}