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); }
@Override public boolean setIfEmpty(T data, long time, TimeUnit units) { long end = System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(time, units); while (!setIfEmpty(data)) { if (end < System.currentTimeMillis()) return false; } return true; }
@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); }
public void start() { inputs = new AtomicReferenceArray<>(0); outputs = inputs; freeReceptors = new CopyOnWriteArrayList<>(); sequence = 0; finalSequence = 0; finalProduct = null; reuseReceptors = new ArrayList<>(0); executor = Executors.newSingleThreadExecutor(); started = true; if (poolSize > 0) { group = new ThreadGroup("FatPipe"); group.setMaxPriority(Thread.MAX_PRIORITY); } signals = new SignalImpl[ARBITARY_THREADS + poolSize]; threads = new Thread[ARBITARY_THREADS + poolSize]; startTime = System.currentTimeMillis(); sleptTime = 0; toSleepTime = 0; for (int i = 0; i < poolSize; i++) { Thread t = new Thread(group, this, name + "-" + i); t.setDaemon(true); threads[i] = t; t.start(); if (sleep == 0) t.setPriority(Thread.MAX_PRIORITY); else if (sleep < 0) t.setPriority(Thread.NORM_PRIORITY); else t.setPriority(Thread.MIN_PRIORITY); } for (int i = 0; i < signals.length; i++) { signals[i] = new SignalImpl(lock); } if (pool != null) pool.add(this); lock.release(); }