Example #1
0
 /// <summary>
 /// Set the interrupt flag and release locks on resources if applicable. The coroutine
 /// is not terminated immediately but rather the next context-switch. Because of this,
 /// Executing Interrupt() does not mean that Completed is set to true immediately, and
 /// that the lock on the resource will be released. Note that it does not immediately
 /// release manually locked objects such as calling CoroutineMonitor.TryEnter within
 /// a coroutine. These objects will never be released.
 /// [TODO] Fixed this.
 /// </summary>
 public void Interrupt()
 {
     suspend   = false;
     interrupt = true;
     // this should remove the resource lock
     if (mutex != null)
     {
         CoroutineMonitor.Exit(mutex);
     }
 }
Example #2
0
        // The coroutine that is started by Unity. This wraps the existing coroutine with
        // additional functions.
        IEnumerator _coroutine()
        {
            // Cache objects to avoid generating unnecessary rubbish.
            var waitToResume = new WaitWhile(isSuspended);

            if (mutex != null)
            {
                // wait to acquire the lock.
                if (!_single)
                {
                    yield return(new WaitUntil(Function.delay(CoroutineMonitor.TryEnter, mutex)));
                }

                SetInUseBy(mutex, this);

                // it is possible for the suspend flag to be set before the coroutine even starts
                // executing, so we will have to pause the execution in such a situation.
                if (suspend)
                {
                    yield return(waitToResume);
                }
            }
            // set the started status flag
            started = true;

            // this if statement is here because it is also possible for the coroutine to be
            // interrupted before execution, specifically while waiting for a lock on the mutex
            // in chained mode. If such a case happens, we do not want the user code to run at all.
            if (!interrupt)
            {
                while (routine.MoveNext())
                {
                    // Due to the syntax of iterators, assume that the user code is executed here.

                    // The yield instruction for user code
                    yield return(routine.Current);

                    // Check if the suspend flag is set before running the next chunk of user code.
                    if (suspend)
                    {
                        yield return(waitToResume);
                    }
                    // Check if the interrupt flag is set before running the next chunk of user
                    // code.
                    if (interrupt)
                    {
                        break;
                    }
                }

                // guarantee execution of dispose block
                routine.Dispose();
            }

            // Release the lock on the mutex if possible. Note that if the interrupt flag is set,
            // Then the Interrupt() function would have already released the lock, so we don't do
            // it twice.
            if (mutex != null && !interrupt)
            {
                CoroutineMonitor.Exit(mutex);
            }

            // Set the complete status flag.
            completed = true;
        }