/// <summary> /// Initialize this cell, i.e. set up mailboxes and supervision. The UID must be /// reasonably different from the previous UID of a possible actor with the same path, /// which can be achieved by using <see cref="ThreadLocalRandom"/> /// </summary> /// <param name="sendSupervise">TBD</param> /// <param name="mailboxType">TBD</param> public void Init(bool sendSupervise, MailboxType mailboxType) { /* * Create the mailbox and enqueue the Create() message to ensure that * this is processed before anything else. */ var mailbox = Dispatcher.CreateMailbox(this, mailboxType); Create createMessage; /* * 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 var actorClass = Props.Type; if (System.Mailboxes.ProducesMessageQueue(mailboxType.GetType()) && System.Mailboxes.HasRequiredType(actorClass)) { var req = System.Mailboxes.GetRequiredType(actorClass); if (req.IsInstanceOfType(mailbox.MessageQueue)) { createMessage = new Create(null); //success } else { var gotType = mailbox.MessageQueue == null ? "null" : mailbox.MessageQueue.GetType().FullName; createMessage = new Create(new ActorInitializationException(Self, $"Actor [{Self}] requires mailbox type [{req}] got [{gotType}]")); } } else { createMessage = new Create(null); } SwapMailbox(mailbox); Mailbox.SetActor(this); //// ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅ var self = Self; mailbox.SystemEnqueue(self, createMessage); if (sendSupervise) { Parent.SendSystemMessage(new Supervise(self, async: false)); } }
/// <summary> /// Initialize this cell, i.e. set up mailboxes and supervision. The UID must be /// reasonably different from the previous UID of a possible actor with the same path, /// which can be achieved by using <see cref="ThreadLocalRandom"/> /// </summary> /// <param name="sendSupervise"></param> /// <param name="mailboxType"></param> public void Init(bool sendSupervise, MailboxType mailboxType) { /* * Create the mailbox and enqueue the Create() message to ensure that * this is processed before anything else. */ var mailbox = Dispatcher.CreateMailbox(this, mailboxType); Create createMessage; /* * 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 var actorClass = Props.Type; if (System.Mailboxes.ProducesMessageQueue(mailboxType.GetType()) && System.Mailboxes.HasRequiredType(actorClass)) { var req = System.Mailboxes.GetRequiredType(actorClass); if (req.IsInstanceOfType(mailbox.MessageQueue)) createMessage = new Create(null); //success else { var gotType = mailbox.MessageQueue == null ? "null" : mailbox.MessageQueue.GetType().FullName; createMessage = new Create(new ActorInitializationException(Self,$"Actor [{Self}] requires mailbox type [{req}] got [{gotType}]")); } } else { createMessage = new Create(null); } SwapMailbox(mailbox); Mailbox.SetActor(this); //// ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅ var self = Self; mailbox.SystemEnqueue(self, createMessage); if(sendSupervise) { Parent.SendSystemMessage(new Supervise(self, async: false)); } }
private Type GetProducedMessageQueueType(MailboxType mailboxType) { var queueType = mailboxType.GetType().GetInterfaces() .Where(i => i.IsGenericType) .Where(i => i.GetGenericTypeDefinition() == ProducesMessageQueueGenericType) .Select(i => i.GetGenericArguments().First()) .FirstOrDefault(); if(queueType == null) throw new ArgumentException(nameof(mailboxType), $"No IProducesMessageQueue<TQueue> supplied for {mailboxType}; illegal mailbox type definition."); return queueType; }