Skip to content

Commit

Permalink
refactor to have features
Browse files Browse the repository at this point in the history
  • Loading branch information
adamhathcock committed Jan 21, 2025
1 parent 2807372 commit 9538f40
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 98 deletions.
10 changes: 7 additions & 3 deletions DUI3/Speckle.Connectors.DUI/Eventing/DelegateReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ public class DelegateReference
private readonly MethodInfo _method;
private readonly Type? _delegateType;

public DelegateReference(Delegate @delegate, bool isAsync)
public DelegateReference(Delegate @delegate, EventFeatures features)
{
var target = @delegate.Target;
_method = @delegate.Method;
if (target != null)
{
if (Attribute.IsDefined(_method.DeclaringType.NotNull(), typeof(CompilerGeneratedAttribute)))
//anonymous methods are always strong....should we do this? - doing a brief search says yes
if (
features.HasFlag(EventFeatures.ForceStrongReference)
|| Attribute.IsDefined(_method.DeclaringType.NotNull(), typeof(CompilerGeneratedAttribute))
)
{
_weakReference = WeakOrStrongReference.CreateStrong(target);
}
Expand All @@ -26,7 +30,7 @@ public DelegateReference(Delegate @delegate, bool isAsync)
}

var messageType = @delegate.Method.GetParameters()[0].ParameterType;
if (isAsync)
if (features.HasFlag(EventFeatures.IsAsync))
{
_delegateType = typeof(Func<,>).MakeGenericType(messageType, typeof(Task));
}
Expand Down
11 changes: 11 additions & 0 deletions DUI3/Speckle.Connectors.DUI/Eventing/EventFeatures.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// ReSharper disable InconsistentNaming
namespace Speckle.Connectors.DUI.Eventing;

[Flags]
public enum EventFeatures
{
None = 0,
OneTime = 1,
IsAsync = 2,
ForceStrongReference = 4
}
35 changes: 31 additions & 4 deletions DUI3/Speckle.Connectors.DUI/Eventing/EventSubscription.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bridge;

namespace Speckle.Connectors.DUI.Eventing;

public class EventSubscription<TPayload>(
DelegateReference actionReference,
IThreadContext threadContext,
ITopLevelExceptionHandler exceptionHandler,
SubscriptionToken token
SubscriptionToken token,
ThreadOption threadOption,
EventFeatures features
) : IEventSubscription
where TPayload : notnull
{
public SubscriptionToken SubscriptionToken => token;

public virtual Func<object[], Task>? GetExecutionStrategy()
public Func<object[], Task>? GetExecutionStrategy()
{
if (!actionReference.IsAlive)
{
Expand All @@ -24,6 +28,29 @@ SubscriptionToken token
};
}

public virtual async Task InvokeAction(TPayload argument) =>
private async Task InvokeAction(TPayload argument)
{
switch (threadOption)
{
case ThreadOption.MainThread:
await threadContext.RunOnMainAsync(() => Invoke(argument));
break;
case ThreadOption.WorkerThread:
await threadContext.RunOnWorkerAsync(() => Invoke(argument));
break;
case ThreadOption.PublisherThread:
default:
await Invoke(argument);
break;
}
}

private async Task Invoke(TPayload argument)
{
await exceptionHandler.CatchUnhandledAsync(() => actionReference.Invoke(argument));
if (features.HasFlag(EventFeatures.OneTime))
{
SubscriptionToken.Dispose();
}
}
}

This file was deleted.

21 changes: 0 additions & 21 deletions DUI3/Speckle.Connectors.DUI/Eventing/OneTimeEventSubscription.cs

This file was deleted.

4 changes: 2 additions & 2 deletions DUI3/Speckle.Connectors.DUI/Eventing/OneTimeThreadedEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public SubscriptionToken OneTimeSubscribe(
}
_activeTokens.Remove(id);
}
token = SubscribeOnceOrNot(action, threadOption, true);
token = Subscribe(action, threadOption, EventFeatures.OneTime);
_activeTokens.Add(id, token);
return token;
}
Expand All @@ -71,7 +71,7 @@ public SubscriptionToken OneTimeSubscribe(
}
_activeTokens.Remove(id);
}
token = SubscribeOnceOrNot(action, threadOption, true);
token = Subscribe(action, threadOption, EventFeatures.OneTime);
_activeTokens.Add(id, token);
return token;
}
Expand Down
45 changes: 11 additions & 34 deletions DUI3/Speckle.Connectors.DUI/Eventing/SpeckleEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,28 @@ public abstract class SpeckleEvent<T>(IThreadContext threadContext, ITopLevelExc

public virtual Task PublishAsync(T payload) => InternalPublish(payload);

protected SubscriptionToken SubscribeOnceOrNot(Func<T, Task> action, ThreadOption threadOption, bool isOnce)
protected SubscriptionToken Subscribe(Func<T, Task> action, ThreadOption threadOption, EventFeatures features)
{
var actionReference = new DelegateReference(action, true);
return SubscribeOnceOrNot(actionReference, threadOption, isOnce);
features |= EventFeatures.IsAsync;
var actionReference = new DelegateReference(action, features);
return Subscribe(actionReference, threadOption, features);
}

protected SubscriptionToken SubscribeOnceOrNot(Action<T> action, ThreadOption threadOption, bool isOnce)
protected SubscriptionToken Subscribe(Action<T> action, ThreadOption threadOption, EventFeatures features)
{
var actionReference = new DelegateReference(action, false);
return SubscribeOnceOrNot(actionReference, threadOption, isOnce);
var actionReference = new DelegateReference(action, features);
return Subscribe(actionReference, threadOption, features);
}

[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
private SubscriptionToken SubscribeOnceOrNot(
private SubscriptionToken Subscribe(
DelegateReference actionReference,
ThreadOption threadOption,
bool isOnce
EventFeatures features
)
{
EventSubscription<T> subscription;
switch (threadOption)
{
case ThreadOption.WorkerThread:
subscription = new WorkerEventSubscription<T>(
actionReference,
threadContext,
exceptionHandler,
new(Unsubscribe),
isOnce
);
break;
case ThreadOption.MainThread:
subscription = new MainThreadEventSubscription<T>(
actionReference,
threadContext,
exceptionHandler,
new(Unsubscribe),
isOnce
);
break;
case ThreadOption.PublisherThread:
default:
subscription = new OneTimeEventSubscription<T>(actionReference, exceptionHandler, new(Unsubscribe), isOnce);
break;
}
EventSubscription<T> subscription =
new(actionReference, threadContext, exceptionHandler, new(Unsubscribe), threadOption, features);
return InternalSubscribe(subscription);
}
}
4 changes: 2 additions & 2 deletions DUI3/Speckle.Connectors.DUI/Eventing/ThreadedEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ public abstract class ThreadedEvent<T>(IThreadContext threadContext, ITopLevelEx
where T : notnull
{
public SubscriptionToken Subscribe(Func<T, Task> action, ThreadOption threadOption = ThreadOption.PublisherThread) =>
SubscribeOnceOrNot(action, threadOption, false);
Subscribe(action, threadOption, EventFeatures.None);

public SubscriptionToken Subscribe(Action<T> action, ThreadOption threadOption = ThreadOption.PublisherThread) =>
SubscribeOnceOrNot(action, threadOption, false);
Subscribe(action, threadOption, EventFeatures.None);
}
16 changes: 0 additions & 16 deletions DUI3/Speckle.Connectors.DUI/Eventing/WorkerEventSubscription.cs

This file was deleted.

0 comments on commit 9538f40

Please sign in to comment.