Exemple #1
0
        public T Receive()
        {
            if (Task.CurrentId == null)
            {
                throw new InvalidOperationException("Tried to receive from a non-Task context");
            }
            if (Task.CurrentId.Value != ownerActorInfo.task.Id)
            {
                throw new InvalidOperationException("Only the owner can receive from a Mailbox");
            }

            if (mailbox.Count <= 0)
            {
                Safety.Assert(waiter == null);
                waiter = runtime.GetCurrentActorInfo();
                Safety.Assert(waiter.enabled);
                waiter.enabled = false;
            }

            runtime.Schedule(OpType.RECEIVE);

            Safety.Assert(mailbox.Count > 0);
            Safety.Assert(waiter == null);

            var res = mailbox[0];

            mailbox.RemoveAt(0);
            return(res);
        }
        private void WaitHelper(ActorInfo actorInfo, ActorInfo otherInfo)
        {
            if (!otherInfo.terminated)
            {
                actorInfo.enabled = false;
                otherInfo.terminateWaiters.Add(actorInfo);
            }

            Schedule(OpType.JOIN);

            Safety.Assert(otherInfo.terminated);
        }
Exemple #3
0
        public void Send(T msg)
        {
            runtime.Schedule(OpType.SEND);
            LogSend(msg);
            mailbox.Add(msg);

            if (waiter != null)
            {
                Safety.Assert(!waiter.enabled);
                waiter.enabled = true;
                waiter         = null;
            }
        }
        public void Schedule(OpType opType, ActorInfo currentActor = null)
        {
            if (currentActor == null)
            {
                currentActor = GetCurrentActorInfo();
            }

            if (CheckTerminated(opType))
            {
                return;
            }

            currentActor.currentOp = opType;

            ActorInfo nextActor = scheduler.GetNext(actorList, currentActor);

            if (nextActor == null)
            {
                foreach (
                    var waiter in
                    actorList.Where(info => info.waitingForDeadlock))
                {
                    waiter.waitingForDeadlock = false;
                    waiter.enabled            = true;
                }
                nextActor = scheduler.GetNext(actorList, currentActor);
            }

            if (nextActor == null)
            {
                // Deadlock
                terminated = true;
                ActivateAllActors();

                CheckTerminated(opType);
                return;
            }

            if (nextActor == currentActor)
            {
                return;
            }

            Safety.Assert(currentActor.active);
            currentActor.active = false;

            lock (nextActor.mutex)
            {
                Safety.Assert(nextActor.enabled);

                Safety.Assert(!nextActor.active);
                nextActor.active = true;

                Monitor.PulseAll(nextActor.mutex);
            }

            lock (currentActor.mutex)
            {
                if (currentActor.terminated && opType == OpType.END)
                {
                    return;
                }

                while (!currentActor.active)
                {
                    Monitor.Wait(currentActor.mutex);
                }

                if (CheckTerminated(opType))
                {
                    return;
                }

                Safety.Assert(currentActor.enabled);
                Safety.Assert(currentActor.active);
            }
        }
        public static T ActorBody <T>(
            Func <T> func,
            TestingActorRuntime runtime,
            bool mainThread,
            ActorInfo info = null)
        {
            if (info == null)
            {
                info = runtime.GetCurrentActorInfo();
            }
            lock (info.mutex)
            {
                Safety.Assert(info.active);
                info.currentOp = OpType.START;

                if (!mainThread)
                {
                    info.active = false;
                    Monitor.PulseAll(info.mutex);

                    while (!info.active)
                    {
                        Monitor.Wait(info.mutex);
                    }
                }
            }

            try
            {
                return(func());
            }
            catch (OperationCanceledException ex)
            {
                lock (info.mutex)
                {
                    if (info.cts.Token ==
                        ex.CancellationToken &&
                        info.cts.IsCancellationRequested)
                    {
                        info.cancelled = true;
                    }
                    info.exceptions.Add(ex);
                }
                throw;
            }
            catch (ActorTerminatedException ex)
            {
                if (mainThread && runtime.error == null)
                {
                    runtime.error = new Exception("Main actor did not terminate.", ex);
                }
            }
            catch (Exception ex)
            {
                runtime.error      = ex;
                runtime.terminated = true;
                runtime.ActivateAllActors();
            }
            finally
            {
                try
                {
                    if (!runtime.terminated)
                    {
                        runtime.Schedule(OpType.END, info);

                        lock (info.mutex)
                        {
                            info.enabled    = false;
                            info.terminated = true;
                            foreach (var waiter in info.terminateWaiters)
                            {
                                waiter.enabled = true;
                            }
                            info.terminateWaiters.Clear();
                        }

                        runtime.Schedule(OpType.END, info);
                    }
                }
                catch (ActorTerminatedException)
                {
                }
                finally
                {
                    lock (info.mutex)
                    {
                        info.terminated = true;
                    }
                }
            }
            return(default(T));
        }