/** * @return if <0, then this pipe should be stopped. If ==0, it should not wait. If >0, if it * should wait */ int execute() { if (!lock.tryAcquire()) return 1; // currently being accessed Thread myThread = Thread.currentThread(); int threadIndex = -1; for (int i = 0; i < threads.length; i++) { if (threads[i] == null) { threads[i] = myThread; threadIndex = i; break; } if (myThread != threads[i]) continue; threadIndex = i; break; } Signal signal; if (threadIndex < 0) { signal = dummySignal; } else { SignalImpl s = signals[threadIndex]; s.threadIndex = threadIndex; s.signaled = false; signal = s; } boolean hasData; try { hasData = poll(signal, null); } finally { signal.signal(); if (threadIndex < 0) lock.release(); } return 0; }
/** * Look for data from all the inputs * * @return true if data was consumed */ private boolean poll(Signal signal, Signal parent) { AtomicReferenceArray<T> o = outputs; for (int i = 0; i < o.length(); i++) { T input = o.getAndSet(i, null); if (input == null) continue; long seq = ++sequence; if (parent != null) parent.signal(); S product = producer.execute(input, reuseReceptors.get(i), signal); signal.signal(); if (!consume(product, seq, 0)) { Thread.yield(); if (!consume(product, seq, 0)) logger.info( "failed to consume product (" + product + ") from producer (" + producer + ")"); } producer.complete(product); return product != null; } return false; }
@Override public Boolean execute(Object d, Receptor<Object> r, Signal parent) { r.lazySet(d); // put the data back in for polling boolean data = false; for (int i = 0; i < children.length; i++) { AtomicIntegerArray inUse = this.inUse; if (!inUse.compareAndSet(i, 0, 1)) { if (inUse.get(i) == 2) sleep(); continue; } PooledFatPipe child = children[i]; if (child == null) { inUse.set(i, 0); continue; } Signal signal; if (parent.getThreadIndex() < 0) { signal = new ChildSignalImpl(inUse, i); } else { ChildSignalImpl s = signals[i * poolSize + parent.getThreadIndex()]; if (s == null || s.inUse != inUse) { sleep(); inUse.set(i, 0); continue; } s.index = i; s.notified = false; signal = s; } try { data |= child.poll(signal, parent); } catch (Exception e) { if (listener == null) logger.error("poll", e); else listener.exceptionThrown(e); } finally { signal.signal(); } } return data ? Boolean.TRUE : null; }