/* * Copyright (C) 2015 Actor LLC. <https://actor.im> */ package im.actor.runtime.actors; import java.util.HashMap; import im.actor.runtime.Runtime; import im.actor.runtime.actors.dispatch.ActorDispatcher; import im.actor.runtime.function.Constructor; /** * Entry point for Actor Model, creates all actors and dispatchers */ public class ActorSystem { public static final float THREAD_MULTIPLIER = 1.5f; public static final int THREAD_MAX_COUNT = 4; private static final ActorSystem mainSystem = new ActorSystem(); /** * Main actor system * * @return ActorSystem */ public static ActorSystem system() { return mainSystem; } private static final String DEFAULT_DISPATCHER = "default"; private final HashMap<String, ActorDispatcher> dispatchers = new HashMap<String, ActorDispatcher>(); private TraceInterface traceInterface; /** * Creating new actor system */ public ActorSystem() { this(true); } /** * Creating new actor system */ public ActorSystem(boolean addDefaultDispatcher) { if (addDefaultDispatcher) { addDispatcher(DEFAULT_DISPATCHER); } } /** * Adding dispatcher with specific threads count * * @param dispatcherId dispatcher id * @param threadsCount threads count */ public void addDispatcher(String dispatcherId, int threadsCount) { synchronized (dispatchers) { if (dispatchers.containsKey(dispatcherId)) { return; } ActorDispatcher dispatcher = new ActorDispatcher(dispatcherId, ThreadPriority.LOW, this, Runtime.isSingleThread() ? 1 : threadsCount); dispatchers.put(dispatcherId, dispatcher); } } /** * Adding dispatcher with threads count = {@code Runtime.getRuntime().availableProcessors()} * * @param dispatcherId dispatcher id */ public void addDispatcher(String dispatcherId) { addDispatcher(dispatcherId, Math.min((int) (Runtime.getCoresCount() * THREAD_MULTIPLIER), THREAD_MAX_COUNT)); } public ActorRef actorOf(ActorSelection selection) { return actorOf(selection.getProps(), selection.getPath()); } /** * Creating or getting existing actor from actor props * * @param props Actor Props * @param path Actor Path * @return ActorRef */ public ActorRef actorOf(Props props, String path) { String dispatcherId = props.getDispatcher() == null ? DEFAULT_DISPATCHER : props.getDispatcher(); ActorDispatcher mailboxesDispatcher; synchronized (dispatchers) { if (!dispatchers.containsKey(dispatcherId)) { throw new RuntimeException("Unknown dispatcherId '" + dispatcherId + "'"); } mailboxesDispatcher = dispatchers.get(dispatcherId); } return mailboxesDispatcher.referenceActor(path, props); } public ActorRef actorOf(String path, Props props) { return actorOf(props, path); } public ActorRef actorOf(String path, ActorCreator creator) { return actorOf(Props.create(creator), path); } public ActorRef actorOf(String path, ActorCreator creator, ActorSupervisor supervisor) { return actorOf(Props.create(creator) .changeSupervisor(supervisor), path); } // public ActorRef actorOf(String path, final Constructor<? extends Actor> constructor) { // return actorOf(Props.create(new ActorCreator() { // @Override // public Actor create() { // return constructor.create(); // } // }), path); // } public ActorRef actorOf(String path, String dispatcher, ActorCreator creator) { return actorOf(Props.create(creator).changeDispatcher(dispatcher), path); } public ActorRef actorOf(String path, String dispatcher, ActorCreator creator, ActorSupervisor supervisor) { return actorOf(Props.create(creator) .changeDispatcher(dispatcher) .changeSupervisor(supervisor), path); } public ActorRef actorOf(String path, String dispatcher, final Constructor<? extends Actor> constructor) { return actorOf(Props.create(new ActorCreator() { @Override public Actor create() { return constructor.create(); } }).changeDispatcher(dispatcher), path); } /** * Getting current trace interface for actor system * * @return trace interface */ public TraceInterface getTraceInterface() { return traceInterface; } /** * Setting current trace interface for actor system * * @param traceInterface trace interface */ public void setTraceInterface(TraceInterface traceInterface) { this.traceInterface = traceInterface; } }