public RoutedActorCell(ActorSystem system, InternalActorRef supervisor, Props routerProps, Props routeeProps, ActorPath path, Mailbox mailbox) : base(system, supervisor, routerProps, path, mailbox) { RouteeProps = routeeProps; routerConfig = routerProps.RouterConfig; Router = routerConfig.CreateRouter(system); routerConfig.Match() .With<Pool>(r => { var routees = new List<Routee>(); for (int i = 0; i < r.NrOfInstances; i++) { var routee = this.ActorOf(RouteeProps); routees.Add(new ActorRefRoutee(routee)); } AddRoutees(routees.ToArray()); }) .With<Group>(r => { var routees = routerConfig.GetRoutees(this).ToArray(); AddRoutees(routees); }); Self = new RoutedActorRef(path, this); }
public ResizablePoolCell(ActorSystem system, InternalActorRef supervisor, Props routerProps, Props routeeProps, ActorPath path, Mailbox mailbox, Pool pool) : base(system, supervisor, routerProps, routeeProps, path, mailbox) { if (pool.Resizer == null) throw new ArgumentException("RouterConfig must be a Pool with defined resizer"); resizer = pool.Resizer; this._pool = pool; this._resizeCounter = 0; this._resizeInProgress = ResizeInProgressState.False; }
public void Setup(BenchmarkContext context) { MsgReceived = context.GetCounter("MsgReceived"); System = ActorSystem.Create("PerfSys"); Action<IActorDsl> actor = d => d.ReceiveAny((o, c) => { MsgReceived.Increment(); }); TestActor = System.ActorOf(Props.Create(() => new Act(actor)), "testactor"); var id = TestActor.Ask<ActorIdentity>(new Identify(null), TimeSpan.FromSeconds(3)).Result; Mailbox = new Mailbox(new UnboundedMessageQueue()); Mailbox.SetActor(TestActor.AsInstanceOf<RepointableActorRef>().Underlying.AsInstanceOf<ActorCell>()); }
public void Init(bool sendSupervise, Func<Mailbox> createMailbox /*, MailboxType mailboxType*/) //TODO: switch from Func<Mailbox> createMailbox to MailboxType mailboxType { var mailbox = createMailbox(); //Akka: dispatcher.createMailbox(this, mailboxType) Dispatcher.Attach(this); mailbox.Setup(Dispatcher); mailbox.SetActor(this); _mailbox = mailbox; var createMessage = new Create(); // AKKA: // /* // * The mailboxType was calculated taking into account what the MailboxType // * has promised to produce. If that was more than the default, then we need // * to reverify here because the dispatcher may well have screwed it up. // */ //// we need to delay the failure to the point of actor creation so we can handle //// it properly in the normal way //val actorClass = props.actorClass //val createMessage = mailboxType match { // case _: ProducesMessageQueue[_] if system.mailboxes.hasRequiredType(actorClass) ⇒ // val req = system.mailboxes.getRequiredType(actorClass) // if (req isInstance mbox.messageQueue) Create(None) // else { // val gotType = if (mbox.messageQueue == null) "null" else mbox.messageQueue.getClass.getName // Create(Some(ActorInitializationException(self, // s"Actor [$self] requires mailbox type [$req] got [$gotType]"))) // } // case _ ⇒ Create(None) //} //swapMailbox(mbox) //mailbox.setActor(this) //// ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅ //mailbox.systemEnqueue(self, createMessage) var self = Self; mailbox.Post(self, new Envelope {Message = createMessage, Sender = self}); if(sendSupervise) { Parent.Tell(new Supervise(self, async: false), self); } }
/// <summary> /// Posts the specified envelope. /// </summary> /// <param name="receiver"></param> /// <param name="envelope"> The envelope. </param> public override void Post(IActorRef receiver, Envelope envelope) { if (_isClosed) { return; } hasUnscheduledMessages = true; if (envelope.Message is ISystemMessage) { Mailbox.DebugPrint("{0} enqueued system message {1} to {2}", ActorCell.Self, envelope, ActorCell.Self.Equals(receiver) ? "itself" : receiver.ToString()); _systemMessages.Enqueue(envelope); } else { Mailbox.DebugPrint("{0} enqueued message {1} to {2}", ActorCell.Self, envelope, ActorCell.Self.Equals(receiver) ? "itself" : receiver.ToString()); _userMessages.Enqueue(envelope); } Schedule(); }
/// <summary> /// Posts the specified envelope. /// </summary> /// <param name="envelope">The envelope.</param> public override void Post(Envelope envelope) { if (_isClosed) { return; } hasUnscheduledMessages = true; if (envelope.Message is SystemMessage) { Mailbox.DebugPrint(ActorCell.Self + " enqueued system message " + envelope); _systemMessages.Enqueue(envelope); } else { Mailbox.DebugPrint(ActorCell.Self + " enqueued message " + envelope); _userMessages.Enqueue(envelope); } Schedule(); }
private void Run() { if (_isClosed) { return; } var throughputDeadlineTime = dispatcher.ThroughputDeadlineTime; ActorCell.UseThreadContext(() => { //if ThroughputDeadlineTime is enabled, start a stopwatch if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0) { if (_deadLineTimer != null) { _deadLineTimer.Restart(); } else { _deadLineTimer = Stopwatch.StartNew(); } } //we are about to process all enqueued messages hasUnscheduledMessages = false; Envelope envelope; //start with system messages, they have the highest priority while (_systemMessages.TryDequeue(out envelope)) { Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope); // TODO: Add + " with " + ActorCell.GetChildren()); dispatcher.SystemDispatch(ActorCell, envelope); } //we should process x messages in this run var left = dispatcher.Throughput; //try dequeue a user message while (!IsSuspended && !_isClosed && _userMessages.TryDequeue(out envelope)) { Mailbox.DebugPrint(ActorCell.Self + " processing message " + envelope); //run the receive handler dispatcher.Dispatch(ActorCell, envelope); //check if any system message have arrived while processing user messages if (_systemMessages.TryDequeue(out envelope)) { //handle system message Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope); // TODO: Add + " with " + ActorCell.GetChildren()); dispatcher.SystemDispatch(ActorCell, envelope); break; } left--; if (_isClosed) { return; } //if deadline time have expired, stop and break if (throughputDeadlineTime.HasValue && throughputDeadlineTime.Value > 0 && _deadLineTimer.Elapsed.Ticks > throughputDeadlineTime.Value) { _deadLineTimer.Stop(); break; } //we are done processing messages for this run if (left == 0) { break; } } Interlocked.Exchange(ref status, MailboxStatus.Idle); //there are still messages that needs to be processed if (_systemMessages.Count > 0 || (!IsSuspended && _userMessages.Count > 0)) { //we still need has unscheduled messages for external info. //e.g. repointable actor ref uses it //TODO: will this be enough for external parties to work? hasUnscheduledMessages = true; //this is subject of a race condition //but that doesn't matter, since if the above "if" misses //the "Post" that adds the new message will still schedule //this specific call is just to deal with existing messages //that wasn't scheduled due to dispatcher throughput being reached //or system messages arriving during user message processing Schedule(); } }); }
/// <summary> /// INTERNAL API /// /// Suggest to register the provided mailbox for execution /// </summary> /// <param name="mbox">The mailbox</param> /// <param name="hasMessageHint">Do we have any messages?</param> /// <param name="hasSystemMessageHint">Do we have any system messages?</param> /// <returns><c>true</c> if the <see cref="Mailbox"/> was scheduled for execution, otherwise <c>false</c>.</returns> internal bool RegisterForExecution(Mailbox mbox, bool hasMessageHint, bool hasSystemMessageHint) { if (mbox.CanBeScheduledForExecution(hasMessageHint, hasSystemMessageHint)) //This needs to be here to ensure thread safety and no races { if (mbox.SetAsScheduled()) { ExecuteTask(mbox); return true; } return false; } return false; }
internal Mailbox SwapMailbox(Mailbox mailbox) { Mailbox.DebugPrint("{0} Swapping mailbox to {1}", Self, mailbox); var ret = _mailboxDoNotCallMeDirectly; #pragma warning disable 420 Interlocked.Exchange(ref _mailboxDoNotCallMeDirectly, mailbox); #pragma warning restore 420 return ret; }
private static InternalActorRef LocalActorOf(ActorSystem system, Props props, InternalActorRef supervisor, ActorPath path, Mailbox mailbox) { ActorCell cell = null; if (props.RouterConfig is NoRouter || props.RouterConfig == null) //TODO: should not need nullcheck here { cell = new ActorCell(system, supervisor, props, path, mailbox); } else { var routeeProps = props.WithRouter(RouterConfig.NoRouter); cell = new RoutedActorCell(system, supervisor, props, routeeProps, path, mailbox); } cell.NewActor(); // parentContext.Watch(cell.Self); return cell.Self; }
private InternalActorRef RemoteActorOf(ActorSystem system, Props props, InternalActorRef supervisor, ActorPath path, Mailbox mailbox) { var scope = (RemoteScope) props.Deploy.Scope; Deploy d = props.Deploy; Address addr = scope.Address; if (HasAddress(addr)) { return LocalActorOf(System, props, supervisor, path, mailbox); } Address localAddress = Transport.LocalAddressForRemote(addr); ActorPath rpath = (new RootActorPath(addr)/"remote"/localAddress.Protocol/localAddress.HostPort()/ path.Elements.Drop(1).ToArray()). WithUid(path.Uid); var remoteRef = new RemoteActorRef(Transport, localAddress, rpath, supervisor, props, d); remoteRef.Start(); return remoteRef; }
private void Run() { if (_isClosed) { return; } ActorCell.UseThreadContext(() => { //if ThroughputDeadlineTime is enabled, start a stopwatch if (dispatcher.ThroughputDeadlineTime.HasValue && dispatcher.ThroughputDeadlineTime.Value > 0) { if (_deadLineTimer != null) { _deadLineTimer.Restart(); } else { _deadLineTimer = Stopwatch.StartNew(); } } //we are about to process all enqueued messages hasUnscheduledMessages = false; Envelope envelope; //start with system messages, they have the highest priority while (_systemMessages.TryDequeue(out envelope)) { Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope); // TODO: Add + " with " + ActorCell.GetChildren()); ActorCell.SystemInvoke(envelope); } //we should process x messages in this run int left = dispatcher.Throughput; //try dequeue a user message while (!_isSuspended && !_isClosed && _userMessages.TryDequeue(out envelope)) { Mailbox.DebugPrint(ActorCell.Self + " processing message " + envelope); //run the receive handler ActorCell.Invoke(envelope); //check if any system message have arrived while processing user messages if (_systemMessages.TryDequeue(out envelope)) { //handle system message Mailbox.DebugPrint(ActorCell.Self + " processing system message " + envelope); // TODO: Add + " with " + ActorCell.GetChildren()); ActorCell.SystemInvoke(envelope); break; } left--; if (_isClosed) { return; } //if deadline time have expired, stop and break if (dispatcher.ThroughputDeadlineTime.HasValue && dispatcher.ThroughputDeadlineTime.Value > 0 && _deadLineTimer.ElapsedTicks > dispatcher.ThroughputDeadlineTime.Value) { _deadLineTimer.Stop(); break; } //we are done processing messages for this run if (left == 0) { break; } } //there are still messages that needs to be processed if (_systemMessages.Count > 0 || (!_isSuspended && _userMessages.Count > 0)) { hasUnscheduledMessages = true; } if (hasUnscheduledMessages) { dispatcher.Schedule(Run); } else { Interlocked.Exchange(ref status, MailboxStatus.Idle); } }); }
//TODO: real akka does this in the RoutedActorRef //Keep this here for now? public static ActorCell NewRouterCell(ActorSystem system, InternalActorRef supervisor, ActorPath path, Props props, Mailbox mailbox,Deploy deploy) { var routerProps = Props.Empty.WithDeploy(deploy); var routeeProps = props.WithRouter(RouterConfig.NoRouter); if (routerProps.RouterConfig is Pool) { var p = routerProps.RouterConfig.AsInstanceOf<Pool>(); if (p.Resizer != null) { //if there is a resizer, use ResizablePoolCell return new ResizablePoolCell(system, supervisor, routerProps, routeeProps, path, mailbox, p); } } //Use RoutedActorCell for all other routers return new RoutedActorCell(system, supervisor, routerProps, routeeProps, path, mailbox); }