103 lines
3.3 KiB
C#
103 lines
3.3 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Threading;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace LeanCloud.Storage.Internal
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// This class represents the internal Unity dispatcher used by the LeanCloud SDK.
|
||
|
///
|
||
|
/// It should be initialized once in your game, usually via AVInitializeBehavior.
|
||
|
///
|
||
|
/// In certain, advanced use-cases, you may wish to use
|
||
|
/// this to set up your dispatcher manually.
|
||
|
/// </summary>
|
||
|
// TODO: (richardross) Review this interface before going public.
|
||
|
public sealed class Dispatcher
|
||
|
{
|
||
|
static Dispatcher()
|
||
|
{
|
||
|
Instance = new Dispatcher();
|
||
|
}
|
||
|
|
||
|
private Dispatcher()
|
||
|
{
|
||
|
DispatcherCoroutine = CreateDispatcherCoroutine();
|
||
|
}
|
||
|
|
||
|
public static Dispatcher Instance { get; private set; }
|
||
|
|
||
|
public GameObject GameObject { get; set; }
|
||
|
public IEnumerator DispatcherCoroutine { get; private set; }
|
||
|
|
||
|
private readonly ReaderWriterLockSlim dispatchQueueLock = new ReaderWriterLockSlim();
|
||
|
private readonly Queue<Action> dispatchQueue = new Queue<Action>();
|
||
|
|
||
|
public void Post(Action action)
|
||
|
{
|
||
|
if (dispatchQueueLock.IsWriteLockHeld)
|
||
|
{
|
||
|
dispatchQueue.Enqueue(action);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dispatchQueueLock.EnterWriteLock();
|
||
|
try
|
||
|
{
|
||
|
dispatchQueue.Enqueue(action);
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
dispatchQueueLock.ExitWriteLock();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private IEnumerator CreateDispatcherCoroutine()
|
||
|
{
|
||
|
// We must stop the first invocation here, so that we don't actually do anything until we begin looping.
|
||
|
yield return null;
|
||
|
while (true)
|
||
|
{
|
||
|
dispatchQueueLock.EnterUpgradeableReadLock();
|
||
|
try
|
||
|
{
|
||
|
// We'll only empty what's already in the dispatch queue in this iteration (so that a
|
||
|
// nested dispatch behaves like nextTick()).
|
||
|
int count = dispatchQueue.Count;
|
||
|
if (count > 0)
|
||
|
{
|
||
|
dispatchQueueLock.EnterWriteLock();
|
||
|
try
|
||
|
{
|
||
|
while (count > 0)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
dispatchQueue.Dequeue()();
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
// If an exception occurs, catch it and log it so that dispatches aren't broken.
|
||
|
Debug.LogException(e);
|
||
|
}
|
||
|
count--;
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
dispatchQueueLock.ExitWriteLock();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
dispatchQueueLock.ExitUpgradeableReadLock();
|
||
|
}
|
||
|
yield return null;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|