コード例 #1
0
    /// <summary>
    /// Starts an async routine in the given <see cref="ExecutionContext"/> and returns an <see cref="AsyncRoutineHandle"/> for that routine.
    /// </summary>
    /// <param name="routine">The enumerator to run as a routine.</param>
    /// <param name="context">The context to start the routine in.</param>
    /// <returns>A <see cref="AsyncRoutineHandle"/> for the routine.</returns>
    public static AsyncRoutineHandle Run(IEnumerator routine, ExecutionContext context)
    {
        Debug.Assert(routine != null, "Routine argument is null.");
        Debug.Assert(Async.GetHandle(routine) == null, "Routine to run is already an active async routine!");

        Async.TryEnsureSingleInstance();

        AsyncRoutineHandle handle = Async.GetOrCreateHandle(routine);

        switch (context)
        {
        case ExecutionContext.Game:
            Async.AdvanceRoutine(routine, ExecutionContext.Game, true);
            break;

        case ExecutionContext.Async:
            Async.QueueAsyncWork(routine);
            break;

        default:
            throw new NotImplementedException(context.ToString());
        }

        // If the routine finished instantly, it might have been deleted from the handle map already.
        // This is okay.

        return(handle);
    }
コード例 #2
0
    /// <summary>
    /// Advances routines that are waiting for fixed update.
    /// </summary>
    private void FixedUpdate()
    {
        lock (Async.WaitingForFixedUpdateRoutinesLock)
        {
            for (int i = 0; i < Async.WaitingForFixedUpdateRoutines.Count; i++)
            {
                Async.AdvanceRoutine(Async.WaitingForFixedUpdateRoutines[i], ExecutionContext.Game, false);
            }

            Async.WaitingForFixedUpdateRoutines.Clear();
        }
    }
コード例 #3
0
    /// <summary>
    /// A vanilla Unity coroutine that waits for end of frame, then advances an async routine that yielded <see cref="WaitForEndOfFrame"/>.
    /// </summary>
    private IEnumerator WaitForEndOfFrameCoroutine(IEnumerator routine, WaitForEndOfFrame waitInstance)
    {
        yield return(waitInstance);

        Async.AdvanceRoutine(routine, ExecutionContext.Game, false);
    }
コード例 #4
0
    /// <summary>
    /// Checks conditions for waiting routines to continue, and advances all game context async routines.
    /// </summary>
    private void Update()
    {
        lock (Async.GameListsLock)
        {
            // Switch active and inactive list, so we can iterate over the now inactive
            // list in peace while the now active list gathers up new requests until the
            // next frame.

            var temp = Async.GameListActive;
            Async.GameListActive   = Async.GameListInactive;
            Async.GameListInactive = temp;
        }

        var list = Async.GameListInactive;

        // Handle routines that are waiting for other routines to complete
        // This code should run very fast as we're just performing a bunch of
        // dictionary lookups and removing items from a list.
        //
        // We can feel okay about holding the lock for the entire time.
        lock (Async.WaitingForRoutineRoutinesLock)
        {
            for (int i = 0; i < Async.WaitingForRoutineRoutines.Count; i++)
            {
                var waitingRoutine = Async.WaitingForRoutineRoutines[i];

                if (Async.GetHandle(waitingRoutine.WaitingForHandle.Routine) == null)
                {
                    // Routine it's waiting for doesn't exist any more; it can now continue.
                    // Remove it from the waiting list and schedule it for execution again.
                    Async.WaitingForRoutineRoutines.RemoveAt(i);
                    i--;

                    if (waitingRoutine.WaitingContext == ExecutionContext.Game)
                    {
                        list.Add(waitingRoutine.Routine);
                    }
                    else
                    {
                        Async.QueueAsyncWork(waitingRoutine.Routine);
                    }
                }
            }
        }

        // Handle routines that are waiting for a certain condition to be fulfilled
        // We are likely just checking a few conditions; this should hopefully be
        // quite fast.
        //
        // We feel less okay about holding the lock for the entire time, but still okay enough.
        lock (Async.WaitingForConditionRoutinesLock)
        {
            for (int i = 0; i < Async.WaitingForConditionRoutines.Count; i++)
            {
                var waitingRoutine = Async.WaitingForConditionRoutines[i];

                if (waitingRoutine.IsConditionFulfilled())
                {
                    // The waiting routine's condition has been fulfilled; it can now continue.
                    // Remove it from the waiting list and schedule it for execution again.
                    Async.WaitingForConditionRoutines.RemoveAt(i);
                    i--;

                    if (waitingRoutine.WaitingContext == ExecutionContext.Game)
                    {
                        list.Add(waitingRoutine.Routine);
                    }
                    else
                    {
                        Async.QueueAsyncWork(waitingRoutine.Routine);
                    }
                }
            }
        }

        // We're about to begin executing the actual game update routines, so start the timer.
        lock (Async.FrameTimerLock)
        {
            Async.FrameTimer.Reset();
            Async.FrameTimer.Start();
        }

        for (int i = 0; i < list.Count; i++)
        {
            Async.AdvanceRoutine(list[i], ExecutionContext.Game, true);
        }

        // Clear the list to free completed routines for GC.
        // Routines that ought to be continued have been added to the currently active list.
        list.Clear();
    }