actor4j.core.XActorThread.java Source code

Java tutorial

Introduction

Here is the source code for actor4j.core.XActorThread.java

Source

/*
 * Copyright (c) 2015-2018, David A. Bauer. All rights reserved.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package actor4j.core;

import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

import org.apache.commons.collections4.queue.CircularFifoQueue;
import org.jctools.queues.MpscArrayQueue;
import org.jctools.queues.MpscLinkedQueue8;

import actor4j.core.messages.ActorMessage;

public class XActorThread extends ActorThread {
    protected Queue<ActorMessage<?>> directiveQueue;
    protected Queue<ActorMessage<?>> priorityQueue;
    protected Queue<ActorMessage<?>> innerQueueL2;
    protected Queue<ActorMessage<?>> innerQueueL1;
    protected Queue<ActorMessage<?>> outerQueueL2B;
    protected Queue<ActorMessage<?>> outerQueueL2A;
    protected Queue<ActorMessage<?>> outerQueueL1;
    protected Queue<ActorMessage<?>> serverQueueL2;
    protected Queue<ActorMessage<?>> serverQueueL1;

    protected AtomicBoolean antiFloodingEnabled;

    protected AtomicBoolean newMessage;

    public XActorThread(ActorSystemImpl system) {
        super(system);

        directiveQueue = new MpscArrayQueue<>(system.getQueueSize());
        priorityQueue = new PriorityBlockingQueue<>(system.getQueueSize());
        serverQueueL2 = new MpscArrayQueue<>(system.getQueueSize());
        serverQueueL1 = new ArrayDeque<>(system.getBufferQueueSize());
        outerQueueL2B = new MpscLinkedQueue8<>();
        outerQueueL2A = new MpscArrayQueue<>(system.getQueueSize());
        outerQueueL1 = new ArrayDeque<>(system.getBufferQueueSize());
        innerQueueL2 = new LinkedList<>();
        innerQueueL1 = new CircularFifoQueue<>(system.getQueueSize());

        antiFloodingEnabled = new AtomicBoolean(false);

        newMessage = new AtomicBoolean(true);
    }

    public void innerQueue(ActorMessage<?> message) {
        if ((((CircularFifoQueue<ActorMessage<?>>) innerQueueL1).isAtFullCapacity() || !innerQueueL2.isEmpty())
                && !antiFloodingEnabled.get())
            innerQueueL2.offer(message);
        else
            innerQueueL1.offer(message);
    }

    public void outerQueue(ActorMessage<?> message) {
        if ((((MpscArrayQueue<ActorMessage<?>>) outerQueueL2A).size() == system.getQueueSize()
                || !outerQueueL2B.isEmpty()) && !antiFloodingEnabled.get())
            outerQueueL2B.offer(message);
        else
            outerQueueL2A.offer(message);
    }

    @Override
    public void onRun() {
        boolean hasNextDirective;
        boolean hasNextPriority;
        int hasNextServer;
        int hasNextOuter;
        int hasNextInner;
        int idle = 0;

        while (!isInterrupted()) {
            hasNextDirective = false;
            hasNextPriority = false;
            hasNextServer = 0;
            hasNextOuter = 0;
            hasNextInner = 0;

            while (poll(directiveQueue))
                hasNextDirective = true;

            while (poll(priorityQueue))
                hasNextPriority = true;

            if (system.clientMode) {
                for (; hasNextServer < system.throughput && poll(serverQueueL1); hasNextServer++)
                    ;
                if (hasNextServer < system.throughput && serverQueueL2.peek() != null) {
                    ActorMessage<?> message = null;
                    for (int j = 0; j < system.getBufferQueueSize()
                            && (message = serverQueueL2.poll()) != null; j++)
                        serverQueueL1.offer(message);

                    for (; hasNextServer < system.throughput && poll(serverQueueL1); hasNextServer++)
                        ;
                }
            }

            for (; hasNextOuter < system.throughput && poll(outerQueueL1); hasNextOuter++)
                ;
            if (hasNextOuter < system.throughput && outerQueueL2A.peek() != null) {
                ActorMessage<?> message = null;
                for (int j = 0; j < system.getBufferQueueSize() && (message = outerQueueL2A.poll()) != null; j++)
                    outerQueueL1.offer(message);

                for (; hasNextOuter < system.throughput && poll(outerQueueL1); hasNextOuter++)
                    ;
            }
            if (hasNextOuter < system.throughput && outerQueueL2B.peek() != null) {
                ActorMessage<?> message = null;
                for (int j = 0; j < system.getBufferQueueSize() && (message = outerQueueL2B.poll()) != null; j++)
                    outerQueueL1.offer(message);

                for (; hasNextOuter < system.throughput && poll(outerQueueL1); hasNextOuter++)
                    ;
            }

            for (; hasNextInner < system.throughput && poll(innerQueueL1); hasNextInner++)
                ;
            if (hasNextInner < system.throughput && innerQueueL2.peek() != null) {
                ActorMessage<?> message = null;
                for (int j = 0; j < system.getQueueSize() && (message = innerQueueL2.poll()) != null; j++)
                    innerQueueL1.offer(message);

                for (; hasNextInner < system.throughput && poll(innerQueueL1); hasNextInner++)
                    ;
            }

            if (hasNextInner == 0 && hasNextOuter == 0 && hasNextServer == 0 && !hasNextPriority
                    && !hasNextDirective) {
                idle++;
                if (idle > system.idle) {
                    idle = 0;
                    if (system.threadMode == ActorThreadMode.PARK) {
                        if (newMessage.compareAndSet(true, false))
                            LockSupport.park(this);
                    } else if (system.threadMode == ActorThreadMode.SLEEP) {
                        try {
                            sleep(system.sleepTime);
                        } catch (InterruptedException e) {
                            interrupt();
                        }
                    } else
                        yield();
                }
            } else
                idle = 0;
        }
    }

    protected void newMessage() {
        if (system.threadMode == ActorThreadMode.PARK && newMessage.compareAndSet(false, true))
            LockSupport.unpark(this);
    }

    public Queue<ActorMessage<?>> getDirectiveQueue() {
        return directiveQueue;
    }

    public Queue<ActorMessage<?>> getPriorityQueue() {
        return priorityQueue;
    }

    public Queue<ActorMessage<?>> getInnerQueue() {
        return innerQueueL1;
    }

    public Queue<ActorMessage<?>> getOuterQueue() {
        return outerQueueL2A;
    }

    public Queue<ActorMessage<?>> getServerQueue() {
        return serverQueueL2;
    }
}