예제 #1
0
파일: Subscriber.java 프로젝트: imace/zava
 /**
  * @warn javadoc description missing
  * @warn param producer not described
  * @param producer
  */
 public void setProducer(Producer producer) {
   long toRequest;
   boolean setProducer = false;
   synchronized (this) {
     toRequest = requested;
     p = producer;
     if (op != null) {
       // middle operator ... we pass thru unless a request has been made
       if (toRequest == Long.MIN_VALUE) {
         // we pass-thru to the next producer as nothing has been requested
         setProducer = true;
       }
     }
   }
   // do after releasing lock
   if (setProducer) {
     op.setProducer(p);
   } else {
     // we execute the request with whatever has been requested (or Long.MAX_VALUE)
     if (toRequest == Long.MIN_VALUE) {
       p.request(Long.MAX_VALUE);
     } else {
       p.request(toRequest);
     }
   }
 }
 public void setProducer(Producer p) {
   synchronized (this) {
     if (emitting) {
       missedProducer = p != null ? p : NULL_PRODUCER;
       return;
     }
     emitting = true;
   }
   boolean skipFinal = false;
   try {
     currentProducer = p;
     long r = requested;
     if (p != null && r != 0) {
       p.request(r);
     }
     emitLoop();
     skipFinal = true;
   } finally {
     if (!skipFinal) {
       synchronized (this) {
         emitting = false;
       }
     }
   }
 }
예제 #3
0
파일: Subscriber.java 프로젝트: imace/zava
 /**
  * Request a certain maximum number of emitted items from the Observable this Subscriber is
  * subscribed to. This is a way of requesting backpressure. To disable backpressure, pass {@code
  * Long.MAX_VALUE} to this method.
  *
  * <p>Requests are additive but if a sequence of requests totals more than {@code Long.MAX_VALUE}
  * then {@code Long.MAX_VALUE} requests will be actioned and the extras <i>may</i> be ignored.
  * Arriving at {@code Long.MAX_VALUE} by addition of requests cannot be assumed to disable
  * backpressure. For example, the code below may result in {@code Long.MAX_VALUE} requests being
  * actioned only.
  *
  * <pre>
  * request(100);
  * request(Long.MAX_VALUE-1);
  * </pre>
  *
  * @param n the maximum number of items you want the Observable to emit to the Subscriber at this
  *     time, or {@code Long.MAX_VALUE} if you want the Observable to emit items at its own pace
  * @throws IllegalArgumentException if {@code n} is negative
  */
 protected final void request(long n) {
   if (n < 0) {
     throw new IllegalArgumentException("number requested cannot be negative: " + n);
   }
   Producer shouldRequest = null;
   synchronized (this) {
     if (p != null) {
       shouldRequest = p;
     } else if (requested == Long.MIN_VALUE) {
       requested = n;
     } else {
       final long total = requested + n;
       // check if overflow occurred
       if (total < 0) {
         requested = Long.MAX_VALUE;
       } else {
         requested = total;
       }
     }
   }
   // after releasing lock
   if (shouldRequest != null) {
     shouldRequest.request(n);
   }
 }
  @Override
  public void request(long n) {
    if (n < 0) {
      throw new IllegalArgumentException("n >= 0 required");
    }
    if (n == 0) {
      return;
    }
    synchronized (this) {
      if (emitting) {
        missedRequested += n;
        return;
      }
      emitting = true;
    }
    boolean skipFinal = false;
    try {
      long r = requested;
      long u = r + n;
      if (u < 0) {
        u = Long.MAX_VALUE;
      }
      requested = u;

      Producer p = currentProducer;
      if (p != null) {
        p.request(n);
      }

      emitLoop();
      skipFinal = true;
    } finally {
      if (!skipFinal) {
        synchronized (this) {
          emitting = false;
        }
      }
    }
  }
  void emitLoop() {
    final Subscriber<? super T> c = child;

    outer:
    for (; ; ) {
      long localRequested;
      Producer localProducer;
      Object localTerminal;
      List<T> q;
      synchronized (this) {
        localRequested = missedRequested;
        localProducer = missedProducer;
        localTerminal = missedTerminal;
        q = queue;
        if (localRequested == 0L && localProducer == null && q == null && localTerminal == null) {
          emitting = false;
          return;
        }
        missedRequested = 0L;
        missedProducer = null;
        queue = null;
        missedTerminal = null;
      }
      boolean empty = q == null || q.isEmpty();
      if (localTerminal != null) {
        if (localTerminal != Boolean.TRUE) {
          c.onError((Throwable) localTerminal);
          return;
        } else if (empty) {
          c.onCompleted();
          return;
        }
      }
      long e = 0;
      if (q != null) {
        for (T v : q) {
          if (c.isUnsubscribed()) {
            return;
          } else if (hasError) {
            continue outer; // if an error has been set, shortcut the loop and act on it
          }
          try {
            c.onNext(v);
          } catch (Throwable ex) {
            Exceptions.throwOrReport(ex, c, v);
            return;
          }
        }
        e += q.size();
      }
      long r = requested;
      // if requested is max, we don't do any accounting
      if (r != Long.MAX_VALUE) {
        // if there were missing requested, add it up
        if (localRequested != 0L) {
          long u = r + localRequested;
          if (u < 0) {
            u = Long.MAX_VALUE;
          }
          r = u;
        }
        // if there were emissions and we don't run on max since the last check, subtract
        if (e != 0L && r != Long.MAX_VALUE) {
          long u = r - e;
          if (u < 0) {
            throw new IllegalStateException("More produced than requested");
          }
          r = u;
        }
        requested = r;
      }
      if (localProducer != null) {
        if (localProducer == NULL_PRODUCER) {
          currentProducer = null;
        } else {
          currentProducer = localProducer;
          if (r != 0L) {
            localProducer.request(r);
          }
        }
      } else {
        Producer p = currentProducer;
        if (p != null && localRequested != 0L) {
          p.request(localRequested);
        }
      }
    }
  }