/// <summary> /// Creates a new actor of the specified <see cref="Type"/>. /// </summary> private Actor CreateActor(ActorId id, Type type, string name, Actor creator, Guid opGroupId) { this.Assert(type.IsSubclassOf(typeof(Actor)), "Type '{0}' is not an actor.", type.FullName); // Using ulong.MaxValue because a Create operation cannot specify // the id of its target, because the id does not exist yet. this.Scheduler.ScheduleNextEnabledOperation(); ResetProgramCounter(creator); if (id is null) { id = new ActorId(type, name, this); } else { this.Assert(id.Runtime is null || id.Runtime == this, "Unbound actor id '{0}' was created by another runtime.", id.Value); this.Assert(id.Type == type.FullName, "Cannot bind actor id '{0}' of type '{1}' to an actor of type '{2}'.", id.Value, id.Type, type.FullName); id.Bind(this); } // The operation group id of the actor is set using the following precedence: // (1) To the specified actor creation operation group id, if it is non-empty. // (2) To the operation group id of the creator actor, if it exists and is non-empty. // (3) To the empty operation group id. if (opGroupId == Guid.Empty && creator != null) { opGroupId = creator.OperationGroupId; } Actor actor = ActorFactory.Create(type); IActorManager actorManager; if (actor is StateMachine stateMachine) { actorManager = new MockStateMachineManager(this, stateMachine, opGroupId); } else { actorManager = new MockActorManager(this, actor, opGroupId); } IEventQueue eventQueue = new MockEventQueue(actorManager, actor); actor.Configure(this, id, actorManager, eventQueue); actor.SetupEventHandlers(); if (this.Configuration.ReportActivityCoverage) { this.ReportActivityCoverageOfActor(actor); } bool result = this.Scheduler.RegisterOperation(new ActorOperation(actor)); this.Assert(result, "Actor id '{0}' is used by an existing or previously halted actor.", id.Value); this.LogWriter.LogCreateActor(id, creator?.Id.Name, creator?.Id.Type); return(actor); }
/// <summary> /// Creates a new actor of the specified <see cref="Type"/>. /// </summary> private Actor CreateActor(ActorId id, Type type, string name, Actor creator, EventGroup group) { this.Assert(type.IsSubclassOf(typeof(Actor)), "Type '{0}' is not an actor.", type.FullName); // Using ulong.MaxValue because a Create operation cannot specify // the id of its target, because the id does not exist yet. this.Scheduler.ScheduleNextOperation(); ResetProgramCounter(creator); if (id is null) { id = new ActorId(type, name, this); } else { this.Assert(id.Runtime is null || id.Runtime == this, "Unbound actor id '{0}' was created by another runtime.", id.Value); this.Assert(id.Type == type.FullName, "Cannot bind actor id '{0}' of type '{1}' to an actor of type '{2}'.", id.Value, id.Type, type.FullName); id.Bind(this); } // If a group was not provided, inherit the current event group from the creator (if any). if (group == null && creator != null) { group = creator.Manager.CurrentEventGroup; } Actor actor = ActorFactory.Create(type); IActorManager actorManager; if (actor is StateMachine stateMachine) { actorManager = new MockStateMachineManager(this, stateMachine, group); } else { actorManager = new MockActorManager(this, actor, group); } IEventQueue eventQueue = new MockEventQueue(actorManager, actor); actor.Configure(this, id, actorManager, eventQueue); actor.SetupEventHandlers(); if (this.Configuration.ReportActivityCoverage) { this.ReportActivityCoverageOfActor(actor); } bool result = this.Scheduler.RegisterOperation(new ActorOperation(actor)); this.Assert(result, "Actor id '{0}' is used by an existing or previously halted actor.", id.Value); if (actor is StateMachine) { this.LogWriter.LogCreateStateMachine(id, creator?.Id.Name, creator?.Id.Type); } else { this.LogWriter.LogCreateActor(id, creator?.Id.Name, creator?.Id.Type); } return(actor); }