// Write an item to the pipe. Don't flush it yet. If incomplete is // set to true the item is assumed to be continued by items // subsequently written to the pipe. Incomplete items are never // flushed down the stream. public final void write(final T value_, boolean incomplete_) { // Place the value to the queue, add new terminator element. queue.push(value_); // Move the "flush up to here" poiter. if (!incomplete_) { f = queue.back_pos(); } }
// Check whether item is available for reading. public final boolean check_read() { // Was the value prefetched already? If so, return. int h = queue.front_pos(); if (h != r) return true; // There's no prefetched value, so let us prefetch more values. // Prefetching is to simply retrieve the // pointer from c in atomic fashion. If there are no // items to prefetch, set c to -1 (using compare-and-swap). if (c.compareAndSet(h, -1)) { // nothing to read, h == r must be the same } else { // something to have been written r = c.get(); } // If there are no elements prefetched, exit. // During pipe's lifetime r should never be NULL, however, // it can happen during pipe shutdown when items // are being deallocated. if (h == r || r == -1) return false; // There was at least one value prefetched. return true; }
// Applies the function fn to the first elemenent in the pipe // and returns the value returned by the fn. // The pipe mustn't be empty or the function crashes. public final T probe() { boolean rc = check_read(); assert (rc); T value = queue.front(); return value; }
// Reads an item from the pipe. Returns false if there is no value. // available. public final T read() { // Try to prefetch a value. if (!check_read()) return null; // There was at least one value prefetched. // Return it to the caller. T value_ = queue.pop(); return value_; }
// Pop an incomplete item from the pipe. Returns true is such // item exists, false otherwise. public T unwrite() { if (f == queue.back_pos()) return null; queue.unpush(); return queue.back(); }
public YPipe(int qsize) { queue = new YQueue<T>(qsize); w = r = f = queue.back_pos(); c = new AtomicInteger(queue.back_pos()); }