All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.onthegomap.planetiler.worker.WeightedHandoffQueue Maven / Gradle / Ivy

package com.onthegomap.planetiler.worker;

import static com.onthegomap.planetiler.util.Exceptions.throwFatalException;

import com.onthegomap.planetiler.collection.IterableOnce;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * A high-performance blocking queue to hand off work from a single producing thread to single consuming thread.
 * 

* Each element has a weight and each batch has a target maximum weight to put more lightweight objects in a batch or * fewer heavy-weight ones. * * @param the type of elements held in this queue */ public class WeightedHandoffQueue implements AutoCloseable, IterableOnce { private final Queue doneSentinel = new ArrayDeque<>(0); private final BlockingQueue> itemQueue; private final int writeLimit; private boolean done = false; private int writeCost = 0; Queue writeBatch = null; Queue readBatch = null; /** * Creates a new {@code WeightedHandoffQueue} with {@code outer} maximum number of pending batches and {@code inner} * maximum batch weight. */ public WeightedHandoffQueue(int outer, int inner) { this.writeLimit = inner; itemQueue = new ArrayBlockingQueue<>(outer); } @Override public void close() { try { flushWrites(); itemQueue.put(doneSentinel); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throwFatalException(e); } catch (Exception e) { throwFatalException(e); } } public void accept(T item, int cost) { if (writeBatch == null) { writeBatch = new ArrayDeque<>(writeLimit / 2); } writeCost += cost; writeBatch.offer(item); if (writeCost >= writeLimit) { flushWrites(); } } private void flushWrites() { if (writeBatch != null && !writeBatch.isEmpty()) { try { Queue oldWriteBatch = writeBatch; writeBatch = null; writeCost = 0; itemQueue.put(oldWriteBatch); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throwFatalException(e); } } } @Override public T get() { Queue itemBatch = readBatch; if (itemBatch == null || itemBatch.isEmpty()) { do { if (done && itemQueue.isEmpty()) { break; } if ((itemBatch = itemQueue.poll()) == null) { try { itemBatch = itemQueue.poll(100, TimeUnit.MILLISECONDS); if (itemBatch != null) { if (itemBatch == doneSentinel) { done = true; } break; } } catch (InterruptedException e) { Thread.currentThread().interrupt(); break;// signal EOF } } else if (itemBatch == doneSentinel) { done = true; } } while (itemBatch == null); readBatch = itemBatch; } return itemBatch == null ? null : itemBatch.poll(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy