How to use CachedDelegate class of Microsoft.Coyote.Actors package

Best Coyote code snippet using Microsoft.Coyote.Actors.CachedDelegate

Actor.cs

Source:Actor.cs Github

copy

Full Screen

...61 private protected IEventQueue Inbox;62 /// <summary>63 /// Map from event types to cached action delegates.64 /// </summary>65 private protected readonly Dictionary<Type, CachedDelegate> ActionMap;66 /// <summary>67 /// Map that contains the active timers.68 /// </summary>69 private protected readonly Dictionary<TimerInfo, IActorTimer> Timers;70 /// <summary>71 /// The current status of the actor. It is marked volatile as72 /// the runtime can read it concurrently.73 /// </summary>74 private protected volatile Status CurrentStatus;75 /// <summary>76 /// Gets the name of the current state, if there is one.77 /// </summary>78 internal string CurrentStateName { get; private protected set; }79 /// <summary>80 /// True if the event handler of the actor is running, else false.81 /// </summary>82 internal bool IsEventHandlerRunning { get; set; }83 /// <summary>84 /// Checks if the actor is halted.85 /// </summary>86 internal bool IsHalted => this.CurrentStatus is Status.Halted;87 /// <summary>88 /// The <see cref="EventGroup"/> currently associated with the actor, if any.89 /// </summary>90 internal EventGroup EventGroup { get; private set; }91 /// <summary>92 /// An optional <see cref="EventGroup"/> associated with the current event being handled.93 /// </summary>94 /// <remarks>95 /// This is an optional argument provided to <see cref="IActorRuntime.CreateActor(ActorId, Type, Event, EventGroup)"/>96 /// or <see cref="IActorRuntime.SendEvent(ActorId, Event, EventGroup, SendOptions)"/>.97 /// </remarks>98 public EventGroup CurrentEventGroup99 {100 get => this.EventGroup == EventGroup.Null ? null : this.EventGroup;101 set102 {103 this.EventGroup = value;104 }105 }106 /// <summary>107 /// The logger installed to the runtime.108 /// </summary>109 /// <remarks>110 /// See <see href="/coyote/concepts/actors/logging" >Logging</see> for more information.111 /// </remarks>112 protected ILogger Logger => this.Context.Logger;113 /// <summary>114 /// User-defined hashed state of the actor. Override to improve the115 /// accuracy of stateful techniques during testing.116 /// </summary>117 protected virtual int HashedState => 0;118 /// <summary>119 /// Initializes a new instance of the <see cref="Actor"/> class.120 /// </summary>121 protected Actor()122 {123 this.ActionMap = new Dictionary<Type, CachedDelegate>();124 this.Timers = new Dictionary<TimerInfo, IActorTimer>();125 this.CurrentStatus = Status.Active;126 this.CurrentStateName = default;127 this.IsEventHandlerRunning = true;128 }129 /// <summary>130 /// Configures the actor.131 /// </summary>132 internal void Configure(ActorExecutionContext context, ActorId id, ActorOperation op, IEventQueue inbox, EventGroup eventGroup)133 {134 this.Context = context;135 this.Id = id;136 this.Operation = op;137 this.Inbox = inbox;138 this.EventGroup = eventGroup;139 }140 /// <summary>141 /// Initializes the actor with the specified optional event.142 /// </summary>143 /// <param name="initialEvent">Optional event used for initialization.</param>144 internal virtual async Task InitializeAsync(Event initialEvent)145 {146 // Invoke the custom initializer, if there is one.147 await this.InvokeUserCallbackAsync(UserCallbackType.OnInitialize, initialEvent);148 if (this.CurrentStatus is Status.Halting)149 {150 await this.HaltAsync(initialEvent);151 }152 }153 /// <summary>154 /// Creates a new actor of the specified type and with the specified optional155 /// <see cref="Event"/>. This <see cref="Event"/> can only be used to access156 /// its payload, and cannot be handled.157 /// </summary>158 /// <param name="type">Type of the actor.</param>159 /// <param name="initialEvent">Optional initialization event.</param>160 /// <param name="eventGroup">An optional event group associated with the new Actor.</param>161 /// <returns>The unique actor id.</returns>162 protected ActorId CreateActor(Type type, Event initialEvent = null, EventGroup eventGroup = null) =>163 this.Context.CreateActor(null, type, null, initialEvent, this, eventGroup);164 /// <summary>165 /// Creates a new actor of the specified type and name, and with the specified166 /// optional <see cref="Event"/>. This <see cref="Event"/> can only be used to167 /// access its payload, and cannot be handled.168 /// </summary>169 /// <param name="type">Type of the actor.</param>170 /// <param name="name">Optional name used for logging.</param>171 /// <param name="initialEvent">Optional initialization event.</param>172 /// <param name="eventGroup">An optional event group associated with the new Actor.</param>173 /// <returns>The unique actor id.</returns>174 protected ActorId CreateActor(Type type, string name, Event initialEvent = null, EventGroup eventGroup = null) =>175 this.Context.CreateActor(null, type, name, initialEvent, this, eventGroup);176 /// <summary>177 /// Creates a new actor of the specified <see cref="Type"/> and name, using the specified178 /// unbound actor id, and passes the specified optional <see cref="Event"/>. This event179 /// can only be used to access its payload, and cannot be handled.180 /// </summary>181 /// <param name="id">Unbound actor id.</param>182 /// <param name="type">Type of the actor.</param>183 /// <param name="name">Optional name used for logging.</param>184 /// <param name="initialEvent">Optional initialization event.</param>185 /// <param name="eventGroup">An optional event group associated with the new Actor.</param>186 protected void CreateActor(ActorId id, Type type, string name, Event initialEvent = null, EventGroup eventGroup = null) =>187 this.Context.CreateActor(id, type, name, initialEvent, this, eventGroup);188 /// <summary>189 /// Sends an asynchronous <see cref="Event"/> to a target.190 /// </summary>191 /// <param name="id">The id of the target.</param>192 /// <param name="e">The event to send.</param>193 /// <param name="eventGroup">An optional event group associated with this Actor.</param>194 /// <param name="options">Optional configuration of a send operation.</param>195 protected void SendEvent(ActorId id, Event e, EventGroup eventGroup = null, SendOptions options = null) =>196 this.Context.SendEvent(id, e, this, eventGroup, options);197 /// <summary>198 /// Waits to receive an <see cref="Event"/> of the specified type199 /// that satisfies an optional predicate.200 /// </summary>201 /// <param name="eventType">The event type.</param>202 /// <param name="predicate">The optional predicate.</param>203 /// <returns>The received event.</returns>204 protected internal Task<Event> ReceiveEventAsync(Type eventType, Func<Event, bool> predicate = null)205 {206 this.Assert(this.CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", this.Id);207 this.OnReceiveInvoked();208 return this.Inbox.ReceiveEventAsync(eventType, predicate);209 }210 /// <summary>211 /// Waits to receive an <see cref="Event"/> of the specified types.212 /// </summary>213 /// <param name="eventTypes">The event types to wait for.</param>214 /// <returns>The received event.</returns>215 protected internal Task<Event> ReceiveEventAsync(params Type[] eventTypes)216 {217 this.Assert(this.CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", this.Id);218 this.OnReceiveInvoked();219 return this.Inbox.ReceiveEventAsync(eventTypes);220 }221 /// <summary>222 /// Waits to receive an <see cref="Event"/> of the specified types223 /// that satisfy the specified predicates.224 /// </summary>225 /// <param name="events">Event types and predicates.</param>226 /// <returns>The received event.</returns>227 protected internal Task<Event> ReceiveEventAsync(params Tuple<Type, Func<Event, bool>>[] events)228 {229 this.Assert(this.CurrentStatus is Status.Active, "{0} invoked ReceiveEventAsync while halting.", this.Id);230 this.OnReceiveInvoked();231 return this.Inbox.ReceiveEventAsync(events);232 }233 /// <summary>234 /// Starts a timer that sends a <see cref="TimerElapsedEvent"/> to this actor after the235 /// specified due time. The timer accepts an optional payload to be used during timeout.236 /// The timer is automatically disposed after it timeouts. To manually stop and dispose237 /// the timer, invoke the <see cref="StopTimer"/> method.238 /// </summary>239 /// <remarks>240 /// See <see href="/coyote/concepts/actors/timers">Using timers in actors</see> for more information.241 /// </remarks>242 /// <param name="startDelay">The amount of time to wait before sending the timeout event.</param>243 /// <param name="customEvent">Optional custom event to raise instead of the default TimerElapsedEvent.</param>244 /// <returns>Handle that contains information about the timer.</returns>245 protected TimerInfo StartTimer(TimeSpan startDelay, TimerElapsedEvent customEvent = null)246 {247 // The specified due time and period must be valid.248 this.Assert(startDelay.TotalMilliseconds >= 0, "{0} registered a timer with a negative due time.", this.Id);249 return this.RegisterTimer(startDelay, Timeout.InfiniteTimeSpan, customEvent);250 }251 /// <summary>252 /// Starts a periodic timer that sends a <see cref="TimerElapsedEvent"/> to this actor after253 /// the specified due time, and then repeats after each specified period. The timer accepts254 /// an optional payload to be used during timeout. The timer can be stopped by invoking the255 /// <see cref="StopTimer"/> method.256 /// </summary>257 /// <remarks>258 /// See <see href="/coyote/concepts/actors/timers">Using timers in actors</see> for more information.259 /// </remarks>260 /// <param name="startDelay">The amount of time to wait before sending the first timeout event.</param>261 /// <param name="period">The time interval between timeout events.</param>262 /// <param name="customEvent">Optional custom event to raise instead of the default TimerElapsedEvent.</param>263 /// <returns>Handle that contains information about the timer.</returns>264 protected TimerInfo StartPeriodicTimer(TimeSpan startDelay, TimeSpan period, TimerElapsedEvent customEvent = null)265 {266 // The specified due time and period must be valid.267 this.Assert(startDelay.TotalMilliseconds >= 0, "{0} registered a periodic timer with a negative due time.", this.Id);268 this.Assert(period.TotalMilliseconds >= 0, "{0} registered a periodic timer with a negative period.", this.Id);269 return this.RegisterTimer(startDelay, period, customEvent);270 }271 /// <summary>272 /// Stops and disposes the specified timer.273 /// </summary>274 /// <remarks>275 /// See <see href="/coyote/concepts/actors/timers">Using timers in actors</see> for more information.276 /// </remarks>277 /// <param name="info">Handle that contains information about the timer.</param>278 protected void StopTimer(TimerInfo info)279 {280 this.Assert(info.OwnerId == this.Id, "{0} is not allowed to dispose timer '{1}', which is owned by {2}.",281 this.Id, info, info.OwnerId);282 this.UnregisterTimer(info);283 }284 /// <summary>285 /// Returns a nondeterministic boolean choice, that can be286 /// controlled during analysis or testing.287 /// </summary>288 /// <returns>The controlled nondeterministic choice.</returns>289 protected bool RandomBoolean() => this.Context.GetNondeterministicBooleanChoice(this.Id.Name, this.Id.Type);290 /// <summary>291 /// Returns a nondeterministic integer, that can be controlled during292 /// analysis or testing. The value is used to generate an integer in293 /// the range [0..maxValue).294 /// </summary>295 /// <param name="maxValue">The max value.</param>296 /// <returns>The controlled nondeterministic integer.</returns>297 protected int RandomInteger(int maxValue) =>298 this.Context.GetNondeterministicIntegerChoice(maxValue, this.Id.Name, this.Id.Type);299 /// <summary>300 /// Invokes the specified monitor with the specified <see cref="Event"/>.301 /// </summary>302 /// <typeparam name="T">Type of the monitor.</typeparam>303 /// <param name="e">Event to send to the monitor.</param>304 protected void Monitor<T>(Event e) => this.Monitor(typeof(T), e);305 /// <summary>306 /// Invokes the specified monitor with the specified event.307 /// </summary>308 /// <param name="type">Type of the monitor.</param>309 /// <param name="e">The event to send.</param>310 protected void Monitor(Type type, Event e)311 {312 this.Assert(e != null, "{0} is sending a null event.", this.Id);313 this.Context.InvokeMonitor(type, e, this.Id.Name, this.Id.Type, this.CurrentStateName);314 }315 /// <summary>316 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.317 /// </summary>318 protected void Assert(bool predicate) => this.Context.Assert(predicate);319 /// <summary>320 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.321 /// </summary>322 protected void Assert(bool predicate, string s, object arg0) => this.Context.Assert(predicate, s, arg0);323 /// <summary>324 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.325 /// </summary>326 protected void Assert(bool predicate, string s, object arg0, object arg1) =>327 this.Context.Assert(predicate, s, arg0, arg1);328 /// <summary>329 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.330 /// </summary>331 protected void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>332 this.Context.Assert(predicate, s, arg0, arg1, arg2);333 /// <summary>334 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.335 /// </summary>336 protected void Assert(bool predicate, string s, params object[] args) =>337 this.Context.Assert(predicate, s, args);338 /// <summary>339 /// Raises a <see cref='HaltEvent'/> to halt the actor at the end of the current action.340 /// </summary>341 protected void RaiseHaltEvent()342 {343 this.Assert(this.CurrentStatus is Status.Active, "{0} invoked Halt while halting.", this.Id);344 this.CurrentStatus = Status.Halting;345 }346 /// <summary>347 /// Asynchronous callback that is invoked when the actor is initialized with an optional event.348 /// </summary>349 /// <param name="initialEvent">Optional event used for initialization.</param>350 /// <returns>Task that represents the asynchronous operation.</returns>351 protected virtual Task OnInitializeAsync(Event initialEvent) => Task.CompletedTask;352 /// <summary>353 /// Asynchronous callback that is invoked when the actor successfully dequeues an event from its inbox.354 /// This method is not called when the dequeue happens via a receive statement.355 /// </summary>356 /// <param name="e">The event that was dequeued.</param>357 protected virtual Task OnEventDequeuedAsync(Event e) => Task.CompletedTask;358 /// <summary>359 /// Callback that is invoked when the actor ignores an event and removes it from its inbox.360 /// </summary>361 /// <param name="e">The event that was ignored.</param>362 protected virtual void OnEventIgnored(Event e)363 {364 }365 /// <summary>366 /// Callback that is invoked when the actor defers dequeing an event from its inbox.367 /// </summary>368 /// <param name="e">The event that was deferred.</param>369 protected virtual void OnEventDeferred(Event e)370 {371 }372 /// <summary>373 /// Asynchronous callback that is invoked when the actor finishes handling a dequeued event, unless374 /// the handler of the dequeued event caused the actor to halt (either normally or due to an exception).375 /// The actor will either become idle or dequeue the next event from its inbox.376 /// </summary>377 /// <param name="e">The event that was handled.</param>378 protected virtual Task OnEventHandledAsync(Event e) => Task.CompletedTask;379 /// <summary>380 /// Asynchronous callback that is invoked when the actor receives an event that it is not381 /// prepared to handle. The callback is invoked first, after which the actor will necessarily382 /// throw an <see cref="UnhandledEventException"/>.383 /// </summary>384 /// <param name="e">The event that was unhandled.</param>385 /// <param name="state">The state when the event was dequeued.</param>386 protected virtual Task OnEventUnhandledAsync(Event e, string state) => Task.CompletedTask;387 /// <summary>388 /// Asynchronous callback that is invoked when the actor handles an exception.389 /// </summary>390 /// <param name="ex">The exception thrown by the actor.</param>391 /// <param name="e">The event being handled when the exception was thrown.</param>392 /// <returns>The action that the runtime should take.</returns>393 protected virtual Task OnExceptionHandledAsync(Exception ex, Event e) => Task.CompletedTask;394 /// <summary>395 /// Asynchronous callback that is invoked when the actor halts.396 /// </summary>397 /// <param name="e">The event being handled when the actor halted.</param>398 /// <returns>Task that represents the asynchronous operation.</returns>399 protected virtual Task OnHaltAsync(Event e) => Task.CompletedTask;400 /// <summary>401 /// Enqueues the specified event and its metadata.402 /// </summary>403 internal EnqueueStatus Enqueue(Event e, EventGroup eventGroup, EventInfo info)404 {405 if (this.CurrentStatus is Status.Halted)406 {407 return EnqueueStatus.Dropped;408 }409 return this.Inbox.Enqueue(e, eventGroup, info);410 }411 /// <summary>412 /// Runs the event handler. The handler terminates if there is no next413 /// event to process or if the actor has halted.414 /// </summary>415 internal async Task RunEventHandlerAsync()416 {417 bool isFreshDequeue = true;418 Event lastDequeuedEvent = null;419 DequeueStatus lastDequeueStatus = DequeueStatus.NoDequeue;420 try421 {422 while (this.CurrentStatus != Status.Halted && this.Context.IsRunning)423 {424 (DequeueStatus status, Event e, EventGroup eventGroup, EventInfo info) = this.Inbox.Dequeue();425 lastDequeueStatus = status;426 if (eventGroup != null)427 {428 this.EventGroup = eventGroup;429 }430 if (status is DequeueStatus.Success)431 {432 // Notify the runtime for a new event to handle. This is only used433 // during bug-finding and operation bounding, because the runtime434 // has to schedule an actor when a new operation is dequeued.435 this.Context.LogDequeuedEvent(this, e, info, isFreshDequeue);436 await this.InvokeUserCallbackAsync(UserCallbackType.OnEventDequeued, e);437 lastDequeuedEvent = e;438 }439 else if (status is DequeueStatus.Raised)440 {441 // Only supported by types (e.g. StateMachine) that allow442 // the user to explicitly raise events.443 this.Context.LogHandleRaisedEvent(this, e);444 }445 else if (status is DequeueStatus.Default)446 {447 this.Context.LogWriter.LogDefaultEventHandler(this.Id, this.CurrentStateName);448 // If the default event was dequeued, then notify the runtime.449 // This is only used during bug-finding, because the runtime must450 // instrument a scheduling point between default event handlers.451 this.Context.LogDefaultEventDequeued(this);452 }453 else if (status is DequeueStatus.Unavailable)454 {455 // Terminate the handler as there is no event available.456 break;457 }458 if (e is TimerElapsedEvent timeoutEvent &&459 timeoutEvent.Info.Period.TotalMilliseconds < 0)460 {461 // If the timer is not periodic, then dispose it.462 this.UnregisterTimer(timeoutEvent.Info);463 }464 if (this.CurrentStatus is Status.Active)465 {466 // Handles the next event, if the actor is not halted.467 await this.HandleEventAsync(e);468 }469 if (!this.Inbox.IsEventRaised && lastDequeuedEvent != null && this.CurrentStatus != Status.Halted)470 {471 // Inform the user that the actor handled the dequeued event.472 await this.InvokeUserCallbackAsync(UserCallbackType.OnEventHandled, lastDequeuedEvent);473 lastDequeuedEvent = null;474 }475 if (this.CurrentStatus is Status.Halting)476 {477 // If the current status is halting, then halt the actor.478 await this.HaltAsync(e);479 }480 isFreshDequeue = false;481 }482 }483 finally484 {485 this.Context.LogEventHandlerTerminated(this, lastDequeueStatus);486 }487 }488 /// <summary>489 /// Handles the specified <see cref="Event"/>.490 /// </summary>491 private protected virtual async Task HandleEventAsync(Event e)492 {493 if (this.ActionMap.TryGetValue(e.GetType(), out CachedDelegate cachedAction) ||494 this.ActionMap.TryGetValue(typeof(WildCardEvent), out cachedAction))495 {496 this.Context.LogInvokedAction(this, cachedAction.MethodInfo, null, null);497 await this.InvokeActionAsync(cachedAction, e);498 }499 else if (e is HaltEvent)500 {501 // If it is the halt event, then change the actor status to halting.502 this.CurrentStatus = Status.Halting;503 }504 else505 {506 await this.InvokeUserCallbackAsync(UserCallbackType.OnEventUnhandled, e);507 if (this.CurrentStatus is Status.Active)508 {509 // If the event cannot be handled then report an error, else halt gracefully.510 var ex = new UnhandledEventException(e, default, "Unhandled Event");511 bool isHalting = this.OnUnhandledEventExceptionHandler(ex, e);512 this.Assert(isHalting, "{0} received event '{1}' that cannot be handled.",513 this.Id, e.GetType().FullName);514 }515 }516 }517 /// <summary>518 /// Invokes the specified action delegate.519 /// </summary>520 private protected async Task InvokeActionAsync(CachedDelegate cachedAction, Event e)521 {522 try523 {524 if (cachedAction.IsAsync)525 {526 Task task = null;527 if (cachedAction.Handler is Func<Event, Task> taskFuncWithEvent)528 {529 task = taskFuncWithEvent(e);530 }531 else if (cachedAction.Handler is Func<Task> taskFunc)532 {533 task = taskFunc();534 }535 this.OnWaitTask(task);536 await task;537 }538 else if (cachedAction.Handler is Action<Event> actionWithEvent)539 {540 actionWithEvent(e);541 }542 else if (cachedAction.Handler is Action action)543 {544 action();545 }546 }547 catch (Exception ex) when (this.OnExceptionHandler(ex, cachedAction.MethodInfo.Name, e))548 {549 // User handled the exception.550 await this.OnExceptionHandledAsync(ex, e);551 }552 catch (Exception ex) when (!cachedAction.IsAsync && this.InvokeOnFailureExceptionFilter(cachedAction, ex))553 {554 // Use an exception filter to call OnFailure before the stack555 // has been unwound. If the exception filter does not fail-fast,556 // it returns false to process the exception normally.557 }558 catch (Exception ex)559 {560 await this.TryHandleActionInvocationExceptionAsync(ex, cachedAction.MethodInfo.Name);561 }562 }563 /// <summary>564 /// Invokes the specified event handler user callback.565 /// </summary>566 private protected async Task InvokeUserCallbackAsync(string callbackType, Event e, string currentState = default)567 {568 try569 {570 Task task = null;571 if (callbackType is UserCallbackType.OnInitialize)572 {573 task = this.OnInitializeAsync(e);574 }575 else if (callbackType is UserCallbackType.OnEventDequeued)576 {577 task = this.OnEventDequeuedAsync(e);578 }579 else if (callbackType is UserCallbackType.OnEventHandled)580 {581 task = this.OnEventHandledAsync(e);582 }583 else if (callbackType is UserCallbackType.OnEventUnhandled)584 {585 task = this.OnEventUnhandledAsync(e, currentState);586 }587 this.OnWaitTask(task);588 await task;589 }590 catch (Exception ex) when (this.OnExceptionHandler(ex, callbackType, e))591 {592 // User handled the exception.593 await this.OnExceptionHandledAsync(ex, e);594 }595 catch (Exception ex)596 {597 // Reports the unhandled exception.598 await this.TryHandleActionInvocationExceptionAsync(ex, callbackType);599 }600 }601 /// <summary>602 /// An exception filter that calls <see cref="CoyoteRuntime.OnFailure"/>,603 /// which can choose to fast-fail the app to get a full dump.604 /// </summary>605 /// <param name="action">The action being executed when the failure occurred.</param>606 /// <param name="ex">The exception being tested.</param>607 private protected bool InvokeOnFailureExceptionFilter(CachedDelegate action, Exception ex)608 {609 // This is called within the exception filter so the stack has not yet been unwound.610 // If the call does not fail-fast, return false to process the exception normally.611 this.Context.RaiseOnFailureEvent(new ActionExceptionFilterException(action.MethodInfo.Name, ex));612 return false;613 }614 /// <summary>615 /// Tries to handle an exception thrown during an action invocation.616 /// </summary>617 private protected Task TryHandleActionInvocationExceptionAsync(Exception ex, string actionName)618 {619 Exception innerException = ex;620 while (innerException is TargetInvocationException)621 {622 innerException = innerException.InnerException;623 }624 if (innerException is AggregateException)625 {626 innerException = innerException.InnerException;627 }628 if (innerException.GetBaseException() is ThreadInterruptedException)629 {630 this.CurrentStatus = Status.Halted;631 Debug.WriteLine($"[coyote::warning] {innerException.GetType().Name} was thrown from {this.Id}.");632 }633 else634 {635 // Reports the unhandled exception.636 this.ReportUnhandledException(innerException, actionName);637 }638 return Task.CompletedTask;639 }640 /// <summary>641 /// Checks if the specified event is ignored.642 /// </summary>643 internal virtual bool IsEventIgnored(Event e) =>644 e is TimerElapsedEvent timeoutEvent && !this.Timers.ContainsKey(timeoutEvent.Info);645 /// <summary>646 /// Checks if the specified event is deferred.647 /// </summary>648 internal virtual bool IsEventDeferred(Event e) => false;649 /// <summary>650 /// Checks if there is a default handler installed.651 /// </summary>652 internal virtual bool IsDefaultHandlerInstalled() => false;653 /// <summary>654 /// Returns the hashed state of this actor.655 /// </summary>656 internal virtual int GetHashedState(SchedulingPolicy policy)657 {658 unchecked659 {660 var hash = 19;661 if (policy is SchedulingPolicy.Interleaving)662 {663 hash = (hash * 31) + this.GetType().GetHashCode();664 hash = (hash * 31) + this.Id.Value.GetHashCode();665 hash = (hash * 31) + this.IsHalted.GetHashCode();666 hash = (hash * 31) + this.IsEventHandlerRunning.GetHashCode();667 hash = (hash * 31) + this.Context.GetActorProgramCounter(this.Id);668 hash = (hash * 31) + this.Inbox.GetCachedState();669 }670 if (this.HashedState != 0)671 {672 // Adds the user-defined hashed state.673 hash = (hash * 31) + this.HashedState;674 }675 return hash;676 }677 }678 /// <summary>679 /// Registers a new timer using the specified configuration.680 /// </summary>681 private protected TimerInfo RegisterTimer(TimeSpan dueTime, TimeSpan period, TimerElapsedEvent customEvent)682 {683 var info = new TimerInfo(this.Id, dueTime, period, customEvent);684 var timer = this.Context.CreateActorTimer(info, this);685 this.Context.LogWriter.LogCreateTimer(info);686 this.Timers.Add(info, timer);687 return info;688 }689 /// <summary>690 /// Unregisters the specified timer.691 /// </summary>692 private protected void UnregisterTimer(TimerInfo info)693 {694 if (!this.Timers.TryGetValue(info, out IActorTimer timer))695 {696 this.Assert(info.OwnerId == this.Id, "Timer '{0}' is already disposed.", info);697 }698 this.Context.LogWriter.LogStopTimer(info);699 this.Timers.Remove(info);700 using (timer)701 {702 // sometimes timer can be null.703 }704 }705 /// <summary>706 /// Extracts user declarations and sets up the event handlers.707 /// </summary>708 internal virtual void SetupEventHandlers()709 {710 if (!ActionCache.ContainsKey(this.GetType()))711 {712 Stack<Type> actorTypes = new Stack<Type>();713 for (var actorType = this.GetType(); typeof(Actor).IsAssignableFrom(actorType); actorType = actorType.BaseType)714 {715 actorTypes.Push(actorType);716 }717 // process base types in reverse order, so mosts derrived type is cached first.718 while (actorTypes.Count > 0)719 {720 this.SetupEventHandlers(actorTypes.Pop());721 }722 }723 // Now we have all derrived types cached, we can build the combined action map for this type.724 for (var actorType = this.GetType(); typeof(Actor).IsAssignableFrom(actorType); actorType = actorType.BaseType)725 {726 // Populates the map of event handlers for this actor instance.727 foreach (var kvp in ActionCache[actorType])728 {729 // use the most derrived action handler for a given event (ignoring any base handlers defined for the same event).730 if (!this.ActionMap.ContainsKey(kvp.Key))731 {732 // MethodInfo.Invoke catches the exception to wrap it in a TargetInvocationException.733 // This unwinds the stack before the ExecuteAction exception filter is invoked, so734 // call through a delegate instead (which is also much faster than Invoke).735 this.ActionMap.Add(kvp.Key, new CachedDelegate(kvp.Value, this));736 }737 }738 }739 }740 private void SetupEventHandlers(Type actorType)741 {742 // If this type has not already been setup in the ActionCache, then we need to try and grab the ActionCacheLock743 // for this type. First make sure we have one and only one lockable object for this type.744 object syncObject = ActionCacheLocks.GetOrAdd(actorType, _ => new object());745 // Locking this syncObject ensures only one thread enters the initialization code to update746 // the ActionCache for this specific Actor type.747 lock (syncObject)748 {749 if (ActionCache.ContainsKey(actorType))...

Full Screen

Full Screen

CachedDelegate.cs

Source:CachedDelegate.cs Github

copy

Full Screen

...7{8 /// <summary>9 /// An actor delegate that has been cached to optimize performance of invocations.10 /// </summary>11 internal class CachedDelegate12 {13 internal readonly MethodInfo MethodInfo;14 internal readonly Delegate Handler;15 internal readonly bool IsAsync;16 internal CachedDelegate(MethodInfo method, object caller)17 {18 ParameterInfo[] parameters = method.GetParameters();19 if (parameters.Length is 1 && method.ReturnType == typeof(void))20 {21 this.Handler = Delegate.CreateDelegate(typeof(Action<Event>), caller, method);22 this.IsAsync = false;23 }24 else if (method.ReturnType == typeof(void))25 {26 this.Handler = Delegate.CreateDelegate(typeof(Action), caller, method);27 this.IsAsync = false;28 }29 else if (parameters.Length is 1 && method.ReturnType == typeof(Task))30 {...

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Actors;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8 {9 static void Main(string[] args)10 {11 var cachedDelegate = new CachedDelegate<int, int>(MyFunction);12 int result = cachedDelegate.Invoke(1);13 Console.WriteLine(result);14 Console.ReadLine();15 }16 private static int MyFunction(int x)17 {18 return x + 1;19 }20 }21}

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Actors;2using System;3using System.Collections.Generic;4using System.Linq;5using System.Text;6using System.Threading.Tasks;7{8 {9 static void Main(string[] args)10 {11 var cachedDelegate = new CachedDelegate<int>(x => x * 2);12 var result = cachedDelegate.Invoke(10);13 Console.WriteLine(result);14 }15 }16}

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using System;2using Microsoft.Coyote.Actors;3using Microsoft.Coyote.Actors.Timers;4{5 {6 static void Main(string[] args)7 {8 var runtime = RuntimeFactory.Create();9 runtime.CreateActor(typeof(CachedDelegateExample));10 runtime.Run();11 }12 }13 {14 private int counter = 0;15 protected override async Task OnInitializeAsync(Event initialEvent)16 {17 var timer = this.RegisterTimer(18 TimeSpan.FromSeconds(1),19 TimeSpan.FromSeconds(1));20 await this.ReceiveEventAsync(typeof(Halt));21 await timer.UnregisterAsync();22 }23 private void OnTimerCallback(object data)24 {25 Console.WriteLine("Counter: {0}", counter++);26 }27 }28}29using System;30using Microsoft.Coyote.Actors;31using Microsoft.Coyote.Actors.Timers;32{33 {34 static void Main(string[] args)35 {36 var runtime = RuntimeFactory.Create();37 runtime.CreateActor(typeof(CachedDelegateExample));38 runtime.Run();39 }40 }41 {42 private int counter = 0;43 protected override async Task OnInitializeAsync(Event initialEvent)44 {45 var timer = this.RegisterTimer(46 TimeSpan.FromSeconds(1),47 TimeSpan.FromSeconds(1));48 await this.ReceiveEventAsync(typeof(Halt));49 await timer.UnregisterAsync();50 }51 private void OnTimerCallback(object data)52 {53 Console.WriteLine("Counter: {0}", counter++);54 }55 }56}57using System;58using Microsoft.Coyote.Actors;59using Microsoft.Coyote.Actors.Timers;60{61 {62 static void Main(string[] args)63 {64 var runtime = RuntimeFactory.Create();65 runtime.CreateActor(typeof(CachedDelegateExample));66 runtime.Run();67 }68 }69 {70 private int counter = 0;71 protected override async Task OnInitializeAsync(Event initialEvent)

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote.Actors;4{5 {6 static void Main(string[] args)7 {8 var cachedDelegate = new CachedDelegate();9 cachedDelegate.RunAsync().Wait();10 }11 }12 {13 public async Task RunAsync()14 {15 var actor = Actor.CreateFromTask(async (IActorRuntime runtime) =>16 {17 var actorId = runtime.CreateActor(typeof(Actor1));18 var actor1 = runtime.GetActorProxy(actorId);19 await actor1.SendEventAsync(new Event1());20 });21 await actor.WaitAsync();22 }23 }24 {25 protected override Task OnInitializeAsync(Event initialEvent)26 {27 this.Runtime.RegisterCachedDelegate(this.Id, "HandleEvent1", this.HandleEvent1);28 return Task.CompletedTask;29 }30 protected override Task OnEventAsync(Event e)31 {32 switch (e)33 {34 this.Runtime.SendEvent(this.Id, "HandleEvent1", e);35 break;36 }37 return Task.CompletedTask;38 }39 private Task HandleEvent1(Event e)40 {41 Console.WriteLine("Handled Event1");42 return Task.CompletedTask;43 }44 }45 {46 }47}48I just tried your example and it works for me. The only difference is that I used the latest version of Coyote (0.2.0-alpha.20200401.1), but I don't think that is the issue. Are you using the latest version of Coyote?49I am using the latest version of Coyote (0.2.0-alpha.20200401.1) and I am using Microsoft.Coyote.Actors package only. I am using Visual Studio

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Actors;2using System;3using System.Threading.Tasks;4using System.Collections.Generic;5using System.Linq;6{7 {8 static async Task Main(string[] args)9 {10 var actor = new Actor();11 var cachedDelegate = new CachedDelegate(actor, nameof(Actor.Foo));12 var result = await cachedDelegate.InvokeAsync(1);13 Console.WriteLine(result);14 }15 }16 {17 public Task<int> Foo(int x)18 {19 return Task.FromResult(x + 1);20 }21 }22}23using Microsoft.Coyote.Actors;24using System;25using System.Threading.Tasks;26using System.Collections.Generic;27using System.Linq;28{29 {30 static async Task Main(string[] args)31 {32 var actor = new Actor();33 var cachedDelegate = new CachedDelegate(actor.Foo);34 var result = await cachedDelegate.InvokeAsync(1);35 Console.WriteLine(result);36 }37 }38 {39 public Task<int> Foo(int x)40 {41 return Task.FromResult(x + 1);42 }43 }44}45using Microsoft.Coyote.Actors;46using System;47using System.Threading.Tasks;48using System.Collections.Generic;49using System.Linq;50{51 {52 static async Task Main(string[] args)53 {54 var actor = new Actor();55 var cachedDelegate = new CachedDelegate(actor.Foo);56 await cachedDelegate.InvokeAsync(1);57 Console.WriteLine("done");58 }59 }60 {

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1{2 public static void Main()3 {4 var actor = new MyActor();5 actor.OnEvent(new MyEvent());6 }7}8{9 public static void Main()10 {11 var actor = new MyActor();12 actor.OnEvent(new MyEvent());13 }14}

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote.Actors;4{5 {6 static void Main(string[] args)7 {8 ActorId actorId = ActorId.CreateRandom();9 ActorRuntime runtime = new ActorRuntime();10 runtime.RegisterActor(typeof(MyActor));11 runtime.CreateActor(typeof(MyActor), actorId);12 CachedDelegate cachedDelegate = new CachedDelegate(actorId, "MyMethod");13 Func<int, Task> myMethod = cachedDelegate.GetDelegate<Func<int, Task>>();14 myMethod(5).Wait();15 }16 }17 {18 [OnEventDoAction(typeof(UnitEvent), nameof(MyMethod))]19 private class Init : State { }20 private async Task MyMethod(Event e)21 {22 int i = (e as IntEvent).Value;23 await Task.Delay(1000);24 Console.WriteLine("MyMethod called with value " + i);25 }26 }27}28CachedDelegate cachedDelegate = new CachedDelegate(actorId, "MyMethod", typeof(int), typeof(string));

Full Screen

Full Screen

CachedDelegate

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Actors;2using System;3using System.Collections.Generic;4using System.Text;5{6 {7 public void TestMethod()8 {9 Console.WriteLine("Hello World");10 }11 }12 {13 public static void Main(string[] args)14 {15 TestClass t = new TestClass();16 CachedDelegate cd = new CachedDelegate(t, "TestMethod");17 cd.Invoke();18 }19 }20}21using Microsoft.Coyote.Actors;22using System;23using System.Collections.Generic;24using System.Text;25{26 {27 public void TestMethod()28 {29 Console.WriteLine("Hello World");30 }31 }32 {33 public static void Main(string[] args)34 {35 TestClass t = new TestClass();36 CachedDelegate cd = new CachedDelegate(t, "TestMethod");37 cd.Invoke();38 }39 }40}41using Microsoft.Coyote.Actors;42using System;43using System.Collections.Generic;44using System.Text;45{46 {47 public void TestMethod()48 {49 Console.WriteLine("Hello World");50 }51 }52 {53 public static void Main(string[] args)54 {55 TestClass t = new TestClass();56 CachedDelegate cd = new CachedDelegate(t, "TestMethod");57 cd.Invoke();58 }59 }60}61using Microsoft.Coyote.Actors;62using System;63using System.Collections.Generic;64using System.Text;65{

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Coyote automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful