/*
* 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;
}
}