1
0
Fork 0
LaboratoryProtection/Assets/Plugins/MessagePipe/Runtime/MessageBroker.cs

210 lines
6.6 KiB
C#
Raw Normal View History

2023-09-12 15:55:51 +08:00
using MessagePipe.Internal;
using System;
using System.Runtime.CompilerServices;
namespace MessagePipe
{
[Preserve]
public class MessageBroker<TMessage> : IPublisher<TMessage>, ISubscriber<TMessage>
{
readonly MessageBrokerCore<TMessage> core;
readonly FilterAttachedMessageHandlerFactory handlerFactory;
[Preserve]
public MessageBroker(MessageBrokerCore<TMessage> core, FilterAttachedMessageHandlerFactory handlerFactory)
{
this.core = core;
this.handlerFactory = handlerFactory;
}
public void Publish(TMessage message)
{
core.Publish(message);
}
public IDisposable Subscribe(IMessageHandler<TMessage> handler, params MessageHandlerFilter<TMessage>[] filters)
{
return core.Subscribe(handlerFactory.CreateMessageHandler(handler, filters));
}
}
[Preserve]
public class MessageBrokerCore<TMessage> : IDisposable, IHandlerHolderMarker
{
readonly FreeList<IMessageHandler<TMessage>> handlers;
readonly MessagePipeDiagnosticsInfo diagnostics;
readonly HandlingSubscribeDisposedPolicy handlingSubscribeDisposedPolicy;
readonly object gate = new object();
bool isDisposed;
[Preserve]
public MessageBrokerCore(MessagePipeDiagnosticsInfo diagnostics, MessagePipeOptions options)
{
this.handlers = new FreeList<IMessageHandler<TMessage>>();
this.handlingSubscribeDisposedPolicy = options.HandlingSubscribeDisposedPolicy;
this.diagnostics = diagnostics;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Publish(TMessage message)
{
var array = handlers.GetValues();
for (int i = 0; i < array.Length; i++)
{
array[i]?.Handle(message);
}
}
public IDisposable Subscribe(IMessageHandler<TMessage> handler)
{
lock (gate)
{
if (isDisposed) return handlingSubscribeDisposedPolicy.Handle(nameof(MessageBrokerCore<TMessage>));
var subscriptionKey = handlers.Add(handler);
var subscription = new Subscription(this, subscriptionKey);
diagnostics.IncrementSubscribe(this, subscription);
return subscription;
}
}
public void Dispose()
{
lock (gate)
{
// Dispose is called when scope is finished.
if (!isDisposed && handlers.TryDispose(out var count))
{
isDisposed = true;
diagnostics.RemoveTargetDiagnostics(this, count);
}
}
}
sealed class Subscription : IDisposable
{
bool isDisposed;
readonly MessageBrokerCore<TMessage> core;
readonly int subscriptionKey;
public Subscription(MessageBrokerCore<TMessage> core, int subscriptionKey)
{
this.core = core;
this.subscriptionKey = subscriptionKey;
}
public void Dispose()
{
if (!isDisposed)
{
isDisposed = true;
lock (core.gate)
{
if (!core.isDisposed)
{
core.handlers.Remove(subscriptionKey, true);
core.diagnostics.DecrementSubscribe(core, this);
}
}
}
}
}
}
[Preserve]
public sealed class BufferedMessageBroker<TMessage> : IBufferedPublisher<TMessage>, IBufferedSubscriber<TMessage>
{
readonly BufferedMessageBrokerCore<TMessage> core;
readonly FilterAttachedMessageHandlerFactory handlerFactory;
[Preserve]
public BufferedMessageBroker(BufferedMessageBrokerCore<TMessage> core, FilterAttachedMessageHandlerFactory handlerFactory)
{
this.core = core;
this.handlerFactory = handlerFactory;
}
public void Publish(TMessage message)
{
core.Publish(message);
}
public IDisposable Subscribe(IMessageHandler<TMessage> handler, params MessageHandlerFilter<TMessage>[] filters)
{
return core.Subscribe(handlerFactory.CreateMessageHandler(handler, filters));
}
}
[Preserve]
public sealed class BufferedMessageBrokerCore<TMessage>
{
static readonly bool IsValueType = typeof(TMessage).IsValueType;
readonly MessageBrokerCore<TMessage> core;
TMessage lastMessage;
[Preserve]
public BufferedMessageBrokerCore(MessageBrokerCore<TMessage> core)
{
this.core = core;
this.lastMessage = default;
}
public void Publish(TMessage message)
{
lastMessage = message;
core.Publish(message);
}
public IDisposable Subscribe(IMessageHandler<TMessage> handler)
{
if (IsValueType || lastMessage != null)
{
handler.Handle(lastMessage);
}
return core.Subscribe(handler);
}
}
// Singleton, Scoped variation
[Preserve]
public class SingletonMessageBroker<TMessage> : MessageBroker<TMessage>, ISingletonPublisher<TMessage>, ISingletonSubscriber<TMessage>
{
[Preserve]
public SingletonMessageBroker(SingletonMessageBrokerCore<TMessage> core, FilterAttachedMessageHandlerFactory handlerFactory)
: base(core, handlerFactory)
{
}
}
[Preserve]
public class ScopedMessageBroker<TMessage> : MessageBroker<TMessage>, IScopedPublisher<TMessage>, IScopedSubscriber<TMessage>
{
[Preserve]
public ScopedMessageBroker(ScopedMessageBrokerCore<TMessage> core, FilterAttachedMessageHandlerFactory handlerFactory)
: base(core, handlerFactory)
{
}
}
[Preserve]
public class SingletonMessageBrokerCore<TMessage> : MessageBrokerCore<TMessage>
{
[Preserve]
public SingletonMessageBrokerCore(MessagePipeDiagnosticsInfo diagnostics, MessagePipeOptions options)
: base(diagnostics, options)
{
}
}
[Preserve]
public class ScopedMessageBrokerCore<TMessage> : MessageBrokerCore<TMessage>
{
[Preserve]
public ScopedMessageBrokerCore(MessagePipeDiagnosticsInfo diagnostics, MessagePipeOptions options)
: base(diagnostics, options)
{
}
}
}