170 lines
5.3 KiB
C#
170 lines
5.3 KiB
C#
/*******************************************************************************
|
||
Copyright © 2015-2022 PICO Technology Co., Ltd.All rights reserved.
|
||
|
||
NOTICE:All information contained herein is, and remains the property of
|
||
PICO Technology Co., Ltd. The intellectual and technical concepts
|
||
contained herein are proprietary to PICO Technology Co., Ltd. and may be
|
||
covered by patents, patents in process, and are protected by trade secret or
|
||
copyright law. Dissemination of this information or reproduction of this
|
||
material is strictly forbidden unless prior written permission is obtained from
|
||
PICO Technology Co., Ltd.
|
||
*******************************************************************************/
|
||
|
||
using System;
|
||
using System.Collections.Concurrent;
|
||
using UnityEngine;
|
||
|
||
namespace Pico.Platform
|
||
{
|
||
public class Looper
|
||
{
|
||
private static readonly ConcurrentDictionary<ulong, Delegate> TaskMap = new ConcurrentDictionary<ulong, Delegate>();
|
||
private static readonly ConcurrentDictionary<MessageType, Delegate> NotifyMap = new ConcurrentDictionary<MessageType, Delegate>();
|
||
public static readonly ConcurrentDictionary<MessageType, MessageParser> MessageParserMap = new ConcurrentDictionary<MessageType, MessageParser>();
|
||
|
||
public static void ProcessMessages(uint limit = 0)
|
||
{
|
||
if (limit == 0)
|
||
{
|
||
while (true)
|
||
{
|
||
var msg = PopMessage();
|
||
if (msg == null)
|
||
{
|
||
break;
|
||
}
|
||
|
||
dispatchMessage(msg);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (var i = 0; i < limit; ++i)
|
||
{
|
||
var msg = PopMessage();
|
||
if (msg == null)
|
||
{
|
||
break;
|
||
}
|
||
|
||
dispatchMessage(msg);
|
||
}
|
||
}
|
||
}
|
||
|
||
public static Message PopMessage()
|
||
{
|
||
if (!CoreService.Initialized)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
var handle = CLIB.ppf_PopMessage();
|
||
if (handle == IntPtr.Zero)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
MessageType messageType = CLIB.ppf_Message_GetType(handle);
|
||
Message msg = MessageQueue.ParseMessage(handle);
|
||
if (msg == null)
|
||
{
|
||
if (MessageParserMap.TryGetValue(messageType, out MessageParser parser))
|
||
{
|
||
msg = parser(handle);
|
||
}
|
||
}
|
||
|
||
if (msg == null)
|
||
{
|
||
Debug.LogError($"Cannot parse message type {messageType}");
|
||
}
|
||
|
||
CLIB.ppf_FreeMessage(handle);
|
||
return msg;
|
||
}
|
||
|
||
private static void dispatchMessage(Message msg)
|
||
{
|
||
if (msg.RequestID != 0)
|
||
{
|
||
// handle task
|
||
if (TaskMap.TryGetValue(msg.RequestID, out var handler))
|
||
{
|
||
try
|
||
{
|
||
handler.DynamicInvoke(msg);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"dispatchMessage failed {e}");
|
||
}
|
||
finally
|
||
{
|
||
TaskMap.TryRemove(msg.RequestID, out handler);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError($"No handler for task: requestId={msg.RequestID}, msg.Type = {msg.Type}. You should call `OnComplete()` when use request API.");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// handle notification
|
||
if (NotifyMap.TryGetValue(msg.Type, out var handler))
|
||
{
|
||
handler.DynamicInvoke(msg);
|
||
}
|
||
else
|
||
{
|
||
//Debug.LogError($"No handler for notification: msg.Type = {msg.Type}");
|
||
}
|
||
}
|
||
}
|
||
|
||
public static void RegisterTaskHandler(ulong taskId, Delegate handler)
|
||
{
|
||
if (taskId == 0)
|
||
{
|
||
Debug.LogError("The task is invalid.");
|
||
return;
|
||
}
|
||
|
||
TaskMap[taskId] = handler;
|
||
}
|
||
|
||
public static void RegisterNotifyHandler(MessageType type, Delegate handler)
|
||
{
|
||
if (handler == null)
|
||
{
|
||
Debug.LogError("Cannot register null notification handler.");
|
||
return;
|
||
}
|
||
|
||
NotifyMap[type] = handler;
|
||
}
|
||
|
||
public static void RegisterMessageParser(MessageType messageType, MessageParser messageParser)
|
||
{
|
||
if (messageParser == null)
|
||
{
|
||
Debug.LogError($"invalid message parser for {messageType}");
|
||
return;
|
||
}
|
||
|
||
if (MessageParserMap.ContainsKey(messageType))
|
||
{
|
||
Debug.LogWarning($"Duplicate register of {messageType}");
|
||
}
|
||
|
||
MessageParserMap.TryAdd(messageType, messageParser);
|
||
}
|
||
|
||
public static void Clear()
|
||
{
|
||
TaskMap.Clear();
|
||
NotifyMap.Clear();
|
||
}
|
||
}
|
||
} |