private void add(PooledFatPipe child) { long start = System.currentTimeMillis(); while (true) { int fails = 0; for (int i = 0; i < inUse.length(); i++) { if (!inUse.compareAndSet(i, 0, 2)) { if (inUse.get(i) != 2) fails++; } } if (fails == 0) break; if (start + 100 < System.currentTimeMillis()) { logger.warn("unable to add cleanly " + toString()); break; } } final AtomicIntegerArray updated = new AtomicIntegerArray(inUse.length() + 1); final List<Integer> needsReset = new ArrayList<>(); for (int i = 0; i < inUse.length(); i++) { int value = inUse.get(i); if (value == 1) { updated.set(i, value); needsReset.add(i); } } final AtomicIntegerArray oldUse = inUse; inUse = updated; signals = new ChildSignalImpl[signals.length + poolSize]; for (int i = 0; i < signals.length; i++) { signals[i] = new ChildSignalImpl(inUse, 0); } children = Arrays.copyOf(children, children.length + 1); children[children.length - 1] = child; scheduleReset(needsReset, oldUse, updated); }
void scheduleReset( List<Integer> needsReset, AtomicIntegerArray oldUse, AtomicIntegerArray updated) { if (needsReset.size() == 0) return; executor.schedule( () -> { for (int i = 0; i < needsReset.size(); i++) { int index = needsReset.get(i); int value = oldUse.get(index); if (value == 0) { updated.set(index, 0); needsReset.remove(i--); } } scheduleReset(needsReset, oldUse, updated); }, 1, TimeUnit.MILLISECONDS); }
@Override public synchronized Receptor<T> takeReceptor() { if (!freeReceptors.isEmpty()) { ReceptorImpl impl = (ReceptorImpl) freeReceptors.remove(0); impl.skips = 0; return impl; } int length = inputs.length() + 1; final AtomicReferenceArray<T> inputs = new AtomicReferenceArray<>(length); this.inputs = inputs; final List<ReceptorImpl> newReuseReceptors = new ArrayList<>(length); for (int i = 0; i < length; i++) { newReuseReceptors.add(new ReceptorImpl(i)); } executor.execute( () -> { long lastTime = System.currentTimeMillis(); try { boolean empty = false; while (!empty && started) { empty = true; for (int i = 0; i < outputs.length(); i++) { T result = outputs.get(i); if (result == null) continue; Thread.sleep(1); empty = false; if (lastTime + 30_000 < System.currentTimeMillis()) { lastTime = System.currentTimeMillis(); logger.error( "unable to set receptors for " + producer + " i=" + i + " result=" + result); if (pool != null) logger.warn("pool=" + pool.producer); } break; } } } catch (InterruptedException e) { logger.warn("takeReceptor", e); } finally { reuseReceptors = newReuseReceptors; outputs = inputs; } }); return new ReceptorImpl(length - 1); }
/** * 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; }