123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- /****************************************************************************
- * Copyright 2019 Nreal Techonology Limited. All rights reserved.
- *
- * This file is part of NRSDK.
- *
- * https://www.nreal.ai/
- *
- *****************************************************************************/
- namespace NRKernal
- {
- using System;
- using System.Collections.Generic;
- using UnityEngine;
- /// <summary> A class used for monitoring the status of an asynchronous task. </summary>
- /// <typeparam name="T"> The resultant type of the task.</typeparam>
- public class AsyncTask<T>
- {
- /// <summary>
- /// A collection of actons to perform on the main Unity thread after the task is complete. </summary>
- private List<Action<T>> m_ActionsUponTaskCompletion;
- /// <summary> Constructor for AsyncTask. </summary>
- /// <param name="asyncOperationComplete"> [out] A callback that, when invoked, changes the status
- /// of the task to complete and sets the result based on
- /// the argument supplied.</param>
- public AsyncTask(out Action<T> asyncOperationComplete)
- {
- // Register for early update event.
- if (!AsyncTask.IsInitialized)
- {
- AsyncTask.Init();
- }
- IsComplete = false;
- asyncOperationComplete = delegate (T result)
- {
- Result = result;
- IsComplete = true;
- if (m_ActionsUponTaskCompletion != null)
- {
- AsyncTask.PerformActionInUpdate(() =>
- {
- for (int i = 0; i < m_ActionsUponTaskCompletion.Count; i++)
- {
- m_ActionsUponTaskCompletion[i](result);
- }
- });
- }
- };
- }
- /// <summary> Constructor for AsyncTask that creates a completed task. </summary>
- /// <param name="result"> The result of the completed task.</param>
- internal AsyncTask(T result)
- {
- Result = result;
- IsComplete = true;
- }
- /// <summary> Gets or sets a value indicating whether the task is complete. </summary>
- /// <value> <c>true</c> if the task is complete, otherwise <c>false</c>. </value>
- public bool IsComplete { get; private set; }
- /// <summary> Gets or sets the result of a completed task. </summary>
- /// <value> The result of the completed task. </value>
- public T Result { get; private set; }
- /// <summary>
- /// Returns a yield instruction that monitors this task for completion within a coroutine. </summary>
- /// <returns> A yield instruction that monitors this task for completion. </returns>
- public CustomYieldInstruction WaitForCompletion()
- {
- return new WaitForTaskCompletionYieldInstruction<T>(this);
- }
- /// <summary>
- /// Performs an action (callback) in the first Unity Update() call after task completion. </summary>
- /// <param name="doAfterTaskComplete"> The action to invoke when task is complete. The result
- /// of the task will be passed as an argument to the action.</param>
- /// <returns> The invoking asynchronous task. </returns>
- public AsyncTask<T> ThenAction(Action<T> doAfterTaskComplete)
- {
- // Perform action now if task is already complete.
- if (IsComplete)
- {
- doAfterTaskComplete(Result);
- return this;
- }
- // Allocate list if needed (avoids allocation if then is not used).
- if (m_ActionsUponTaskCompletion == null)
- {
- m_ActionsUponTaskCompletion = new List<Action<T>>();
- }
- m_ActionsUponTaskCompletion.Add(doAfterTaskComplete);
- return this;
- }
- }
- /// <summary> Helper methods for dealing with asynchronous tasks. </summary>
- internal class AsyncTask
- {
- /// <summary> Queue of update actions. </summary>
- private static Queue<Action> m_UpdateActionQueue = new Queue<Action>();
- /// <summary> The lock object. </summary>
- private static object m_LockObject = new object();
- /// <summary> Gets or sets a value indicating whether this object is initialized. </summary>
- /// <value> True if this object is initialized, false if not. </value>
- public static bool IsInitialized { get; private set; }
- /// <summary>
- /// Queues an action to be performed on Unity thread in Update(). This method can be called by
- /// any thread. </summary>
- /// <param name="action"> The action to perform.</param>
- public static void PerformActionInUpdate(Action action)
- {
- lock (m_LockObject)
- {
- m_UpdateActionQueue.Enqueue(action);
- }
- }
- /// <summary> An Update handler called each frame. </summary>
- public static void OnUpdate()
- {
- if (m_UpdateActionQueue.Count == 0)
- {
- return;
- }
- lock (m_LockObject)
- {
- while (m_UpdateActionQueue.Count > 0)
- {
- Action action = m_UpdateActionQueue.Dequeue();
- action();
- }
- }
- }
- /// <summary> Initializes this object. </summary>
- public static void Init()
- {
- if (IsInitialized)
- {
- return;
- }
- NRKernalUpdater.OnUpdate += OnUpdate;
- IsInitialized = true;
- }
- }
- }
|