
com.github.davidmoten.rx.internal.operators.FileBasedSPSCQueueMemoryMapped Maven / Gradle / Ivy
package com.github.davidmoten.rx.internal.operators;
import java.io.File;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import com.github.davidmoten.rx.buffertofile.DataSerializer;
import com.github.davidmoten.rx.internal.operators.FileBasedSPSCQueueMemoryMappedReaderWriter.EOFRuntimeException;
import com.github.davidmoten.util.Preconditions;
import rx.functions.Func0;
public final class FileBasedSPSCQueueMemoryMapped implements QueueWithSubscription {
private final Queue> inactive = new LinkedList>();
private final Deque> toRead = new ArrayDeque>();
private final Object lock = new Object();
private final Func0 factory;
private final int size;
// only needs to be visible to thread calling poll()
private FileBasedSPSCQueueMemoryMappedReaderWriter reader;
// only needs to be visible to thread calling offer()
private FileBasedSPSCQueueMemoryMappedReaderWriter writer;
private final AtomicInteger wip = new AtomicInteger();
private volatile boolean unsubscribed = false;
private final AtomicLong count = new AtomicLong();
private final DataSerializer serializer;
public FileBasedSPSCQueueMemoryMapped(Func0 factory, int size,
DataSerializer serializer) {
Preconditions.checkNotNull(factory);
Preconditions.checkNotNull(serializer);
this.factory = factory;
this.size = size;
this.serializer = serializer;
File file = factory.call();
this.writer = new FileBasedSPSCQueueMemoryMappedReaderWriter(file, size, serializer);
this.reader = writer.openForWrite().openForRead();
// store store barrier
wip.lazySet(0);
}
@Override
public void unsubscribe() {
wip.incrementAndGet();
unsubscribed = true;
checkUnsubscribe();
}
@Override
public boolean isUnsubscribed() {
return unsubscribed;
}
@Override
public synchronized boolean offer(T t) {
// thread safe with poll() and unsubscribe()
try {
wip.incrementAndGet();
if (unsubscribed)
return true;
if (!writer.offer(t)) {
// note that writer will be in a closed state if we follow this
// path
FileBasedSPSCQueueMemoryMappedReaderWriter nextWriter;
synchronized (lock) {
nextWriter = inactive.poll();
if (nextWriter == null) {
nextWriter = new FileBasedSPSCQueueMemoryMappedReaderWriter(
factory.call(), size, serializer);
}
toRead.offerLast(nextWriter);
nextWriter.openForWrite();
}
writer = nextWriter;
return writer.offer(t);
} else {
return true;
}
} finally {
checkUnsubscribe();
count.incrementAndGet();
}
}
private void checkUnsubscribe() {
// single ampersand because we must call wip.decrementAndGet
if (unsubscribed & wip.decrementAndGet() == 0) {
close();
}
}
private void close() {
writer.close();
reader.close();
}
@Override
public synchronized T poll() {
T value = null;
// thread safe with offer() and unsubscribe()
try {
wip.incrementAndGet();
if (unsubscribed)
return null;
value = reader.poll();
return value;
} catch (EOFRuntimeException e) {
FileBasedSPSCQueueMemoryMappedReaderWriter nextReader;
synchronized (lock) {
if (toRead.isEmpty()) {
return null;
} else {
nextReader = toRead.pollFirst();
}
reader.closeForRead();
inactive.offer(reader);
}
reader = nextReader;
reader.openForRead();
value = reader.poll();
return value;
} finally {
checkUnsubscribe();
if (value != null) {
count.decrementAndGet();
}
}
}
@Override
public int size() {
throw new UnsupportedOperationException();
}
@Override
public boolean isEmpty() {
return count.get() == 0;
}
@Override
public boolean contains(Object o) {
throw new UnsupportedOperationException();
}
@Override
public Iterator iterator() {
throw new UnsupportedOperationException();
}
@Override
public Object[] toArray() {
throw new UnsupportedOperationException();
}
@SuppressWarnings("hiding")
@Override
public T[] toArray(T[] a) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
@Override
public boolean containsAll(Collection> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection extends T> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean removeAll(Collection> c) {
throw new UnsupportedOperationException();
}
@Override
public boolean retainAll(Collection> c) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public boolean add(T e) {
throw new UnsupportedOperationException();
}
@Override
public T remove() {
throw new UnsupportedOperationException();
}
@Override
public T element() {
throw new UnsupportedOperationException();
}
@Override
public T peek() {
throw new UnsupportedOperationException();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy