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

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 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