Skip to content

Commit 703c57f

Browse files
committed
More code refactoring
1 parent 6551d55 commit 703c57f

File tree

6 files changed

+90
-85
lines changed

6 files changed

+90
-85
lines changed

CommunityToolkit.WinUI/Extensions/DispatcherQueueExtensions{T}.cs

Lines changed: 39 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,7 @@ public static partial class DispatcherQueueExtensions
4747
public static unsafe bool TryEnqueue<T>(this DispatcherQueue dispatcherQueue, DispatcherQueueHandler<T> callback, T state)
4848
where T : class
4949
{
50-
IDispatcherQueue* dispatcherQueuePtr = (IDispatcherQueue*)((IWinRTObject)dispatcherQueue).NativeObject.ThisPtr;
51-
DispatcherQueueProxyHandler1* dispatcherQueueHandlerPtr = DispatcherQueueProxyHandler1.Create(callback, state);
52-
53-
bool success;
54-
int hResult;
55-
56-
try
57-
{
58-
hResult = dispatcherQueuePtr->TryEnqueue(dispatcherQueueHandlerPtr, (byte*)&success);
59-
60-
GC.KeepAlive(dispatcherQueue);
61-
}
62-
finally
63-
{
64-
dispatcherQueueHandlerPtr->Release();
65-
}
66-
67-
if (hResult != 0)
68-
{
69-
ExceptionHelpers.ThrowExceptionForHR(hResult);
70-
}
71-
72-
return success;
50+
return TryEnqueue(dispatcherQueue, DispatcherQueueProxyHandler1.Create(callback, state));
7351
}
7452

7553
/// <summary>
@@ -85,29 +63,7 @@ public static unsafe bool TryEnqueue<T>(this DispatcherQueue dispatcherQueue, Di
8563
public static unsafe bool TryEnqueue<T>(this DispatcherQueue dispatcherQueue, DispatcherQueuePriority priority, DispatcherQueueHandler<T> callback, T state)
8664
where T : class
8765
{
88-
IDispatcherQueue* dispatcherQueuePtr = (IDispatcherQueue*)((IWinRTObject)dispatcherQueue).NativeObject.ThisPtr;
89-
DispatcherQueueProxyHandler1* dispatcherQueueHandlerPtr = DispatcherQueueProxyHandler1.Create(callback, state);
90-
91-
bool success;
92-
int hResult;
93-
94-
try
95-
{
96-
hResult = dispatcherQueuePtr->TryEnqueueWithPriority(priority, dispatcherQueueHandlerPtr, (byte*)&success);
97-
98-
GC.KeepAlive(dispatcherQueue);
99-
}
100-
finally
101-
{
102-
dispatcherQueueHandlerPtr->Release();
103-
}
104-
105-
if (hResult != 0)
106-
{
107-
ExceptionHelpers.ThrowExceptionForHR(hResult);
108-
}
109-
110-
return success;
66+
return TryEnqueue(dispatcherQueue, priority, DispatcherQueueProxyHandler1.Create(callback, state));
11167
}
11268

11369
/// <summary>
@@ -124,22 +80,52 @@ public static unsafe bool TryEnqueue<T>(this DispatcherQueue dispatcherQueue, Di
12480
public static unsafe bool TryEnqueue<T1, T2>(this DispatcherQueue dispatcherQueue, DispatcherQueueHandler<T1, T2> callback, T1 state1, T2 state2)
12581
where T1 : class
12682
where T2 : class
83+
{
84+
return TryEnqueue(dispatcherQueue, DispatcherQueueProxyHandler2.Create(callback, state1, state2));
85+
}
86+
87+
/// <summary>
88+
/// Adds a task to the <see cref="DispatcherQueue"/> which will be executed on the thread associated with it.
89+
/// </summary>
90+
/// <typeparam name="T1">The type of the first state to capture.</typeparam>
91+
/// <typeparam name="T2">The type of the second state to capture.</typeparam>
92+
/// <param name="dispatcherQueue">The target <see cref="DispatcherQueue"/> to invoke the code on.</param>
93+
/// <param name="priority"> The desired priority for the callback to schedule.</param>
94+
/// <param name="callback">The input <see cref="DispatcherQueueHandler{T}"/> callback to enqueue.</param>
95+
/// <param name="state1">The first input state to capture and pass to the callback.</param>
96+
/// <param name="state2">The second input state to capture and pass to the callback.</param>
97+
/// <returns>Whether or not the task was added to the queue.</returns>
98+
/// <exception cref="Exception">Thrown when the enqueue operation fails.</exception>
99+
public static unsafe bool TryEnqueue<T1, T2>(this DispatcherQueue dispatcherQueue, DispatcherQueuePriority priority, DispatcherQueueHandler<T1, T2> callback, T1 state1, T2 state2)
100+
where T1 : class
101+
where T2 : class
102+
{
103+
return TryEnqueue(dispatcherQueue, priority, DispatcherQueueProxyHandler2.Create(callback, state1, state2));
104+
}
105+
106+
/// <summary>
107+
/// Adds a task to the <see cref="DispatcherQueue"/> which will be executed on the thread associated with it.
108+
/// </summary>
109+
/// <param name="dispatcherQueue">The target <see cref="DispatcherQueue"/> to invoke the code on.</param>
110+
/// <param name="dispatcherQueueHandler">The input callback to enqueue.</param>
111+
/// <returns>Whether or not the task was added to the queue.</returns>
112+
/// <exception cref="Exception">Thrown when the enqueue operation fails.</exception>
113+
private static unsafe bool TryEnqueue(DispatcherQueue dispatcherQueue, IDispatcherQueueHandler* dispatcherQueueHandler)
127114
{
128115
IDispatcherQueue* dispatcherQueuePtr = (IDispatcherQueue*)((IWinRTObject)dispatcherQueue).NativeObject.ThisPtr;
129-
DispatcherQueueProxyHandler2* dispatcherQueueHandlerPtr = DispatcherQueueProxyHandler2.Create(callback, state1, state2);
130116

131117
bool success;
132118
int hResult;
133119

134120
try
135121
{
136-
hResult = dispatcherQueuePtr->TryEnqueue(dispatcherQueueHandlerPtr, (byte*)&success);
122+
hResult = dispatcherQueuePtr->TryEnqueue(dispatcherQueueHandler, (byte*)&success);
137123

138124
GC.KeepAlive(dispatcherQueue);
139125
}
140126
finally
141127
{
142-
dispatcherQueueHandlerPtr->Release();
128+
dispatcherQueueHandler->Release();
143129
}
144130

145131
if (hResult != 0)
@@ -153,34 +139,27 @@ public static unsafe bool TryEnqueue<T1, T2>(this DispatcherQueue dispatcherQueu
153139
/// <summary>
154140
/// Adds a task to the <see cref="DispatcherQueue"/> which will be executed on the thread associated with it.
155141
/// </summary>
156-
/// <typeparam name="T1">The type of the first state to capture.</typeparam>
157-
/// <typeparam name="T2">The type of the second state to capture.</typeparam>
158142
/// <param name="dispatcherQueue">The target <see cref="DispatcherQueue"/> to invoke the code on.</param>
159143
/// <param name="priority"> The desired priority for the callback to schedule.</param>
160-
/// <param name="callback">The input <see cref="DispatcherQueueHandler{T}"/> callback to enqueue.</param>
161-
/// <param name="state1">The first input state to capture and pass to the callback.</param>
162-
/// <param name="state2">The second input state to capture and pass to the callback.</param>
144+
/// <param name="dispatcherQueueHandler">The input callback to enqueue.</param>
163145
/// <returns>Whether or not the task was added to the queue.</returns>
164146
/// <exception cref="Exception">Thrown when the enqueue operation fails.</exception>
165-
public static unsafe bool TryEnqueue<T1, T2>(this DispatcherQueue dispatcherQueue, DispatcherQueuePriority priority, DispatcherQueueHandler<T1, T2> callback, T1 state1, T2 state2)
166-
where T1 : class
167-
where T2 : class
147+
private static unsafe bool TryEnqueue(DispatcherQueue dispatcherQueue, DispatcherQueuePriority priority, IDispatcherQueueHandler* dispatcherQueueHandler)
168148
{
169149
IDispatcherQueue* dispatcherQueuePtr = (IDispatcherQueue*)((IWinRTObject)dispatcherQueue).NativeObject.ThisPtr;
170-
DispatcherQueueProxyHandler2* dispatcherQueueHandlerPtr = DispatcherQueueProxyHandler2.Create(callback, state1, state2);
171150

172151
bool success;
173152
int hResult;
174153

175154
try
176155
{
177-
hResult = dispatcherQueuePtr->TryEnqueueWithPriority(priority, dispatcherQueueHandlerPtr, (byte*)&success);
156+
hResult = dispatcherQueuePtr->TryEnqueueWithPriority(priority, dispatcherQueueHandler, (byte*)&success);
178157

179158
GC.KeepAlive(dispatcherQueue);
180159
}
181160
finally
182161
{
183-
dispatcherQueueHandlerPtr->Release();
162+
dispatcherQueueHandler->Release();
184163
}
185164

186165
if (hResult != 0)

CommunityToolkit.WinUI/Extensions/Interop/DispatcherQueueProxyHandler1.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ internal unsafe struct DispatcherQueueProxyHandler1
6767
private volatile uint referenceCount;
6868

6969
/// <summary>
70-
/// Creates a new <see cref="DispatcherQueueProxyHandler1"/> instance for the input callback and state.
70+
/// Creates a new <see cref="IDispatcherQueueHandler"/> instance for the input callback and state.
7171
/// </summary>
7272
/// <param name="handler">The input <see cref="DispatcherQueueHandler{TState}"/> callback to enqueue.</param>
7373
/// <param name="state">The input state to capture and pass to the callback.</param>
74-
/// <returns>A pointer to the newly initialized <see cref="DispatcherQueueProxyHandler1"/> instance.</returns>
75-
public static DispatcherQueueProxyHandler1* Create(object handler, object state)
74+
/// <returns>A pointer to the newly initialized <see cref="IDispatcherQueueHandler"/> instance.</returns>
75+
public static IDispatcherQueueHandler* Create(object handler, object state)
7676
{
7777
DispatcherQueueProxyHandler1* @this = (DispatcherQueueProxyHandler1*)Marshal.AllocHGlobal(sizeof(DispatcherQueueProxyHandler1));
7878

@@ -81,7 +81,7 @@ internal unsafe struct DispatcherQueueProxyHandler1
8181
@this->stateHandle = GCHandle.Alloc(state);
8282
@this->referenceCount = 1;
8383

84-
return @this;
84+
return (IDispatcherQueueHandler*)@this;
8585
}
8686

8787
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -118,9 +118,9 @@ private static class Impl
118118
[UnmanagedCallersOnly]
119119
public static int QueryInterface(DispatcherQueueProxyHandler1* @this, Guid* riid, void** ppvObject)
120120
{
121-
if (riid->Equals(IUnknown) ||
122-
riid->Equals(IAgileObject) ||
123-
riid->Equals(IDispatcherQueueHandler))
121+
if (riid->Equals(GuidOfIUnknown) ||
122+
riid->Equals(GuidOfIAgileObject) ||
123+
riid->Equals(GuidOfIDispatcherQueueHandler))
124124
{
125125
@this->AddRef();
126126

CommunityToolkit.WinUI/Extensions/Interop/DispatcherQueueProxyHandler2.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,13 @@ internal unsafe struct DispatcherQueueProxyHandler2
7272
private volatile uint referenceCount;
7373

7474
/// <summary>
75-
/// Creates a new <see cref="DispatcherQueueProxyHandler2"/> instance for the input callback and state.
75+
/// Creates a new <see cref="IDispatcherQueueHandler"/> instance for the input callback and state.
7676
/// </summary>
7777
/// <param name="handler">The input <see cref="DispatcherQueueHandler{T1,T2}"/> callback to enqueue.</param>
7878
/// <param name="state1">The first input state to capture and pass to the callback.</param>
7979
/// <param name="state2">The second input state to capture and pass to the callback.</param>
80-
/// <returns>A pointer to the newly initialized <see cref="DispatcherQueueProxyHandler2"/> instance.</returns>
81-
public static DispatcherQueueProxyHandler2* Create(object handler, object state1, object state2)
80+
/// <returns>A pointer to the newly initialized <see cref="IDispatcherQueueHandler"/> instance.</returns>
81+
public static IDispatcherQueueHandler* Create(object handler, object state1, object state2)
8282
{
8383
DispatcherQueueProxyHandler2* @this = (DispatcherQueueProxyHandler2*)Marshal.AllocHGlobal(sizeof(DispatcherQueueProxyHandler2));
8484

@@ -88,7 +88,7 @@ internal unsafe struct DispatcherQueueProxyHandler2
8888
@this->state2Handle = GCHandle.Alloc(state2);
8989
@this->referenceCount = 1;
9090

91-
return @this;
91+
return (IDispatcherQueueHandler*)@this;
9292
}
9393

9494
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -126,9 +126,9 @@ private static class Impl
126126
[UnmanagedCallersOnly]
127127
public static int QueryInterface(DispatcherQueueProxyHandler2* @this, Guid* riid, void** ppvObject)
128128
{
129-
if (riid->Equals(IUnknown) ||
130-
riid->Equals(IAgileObject) ||
131-
riid->Equals(IDispatcherQueueHandler))
129+
if (riid->Equals(GuidOfIUnknown) ||
130+
riid->Equals(GuidOfIAgileObject) ||
131+
riid->Equals(GuidOfIDispatcherQueueHandler))
132132
{
133133
@this->AddRef();
134134

CommunityToolkit.WinUI/Extensions/Interop/IDispatcherQueue.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
using System.Runtime.CompilerServices;
66
using Microsoft.UI.Dispatching;
77

8-
#nullable enable
9-
108
#pragma warning disable CS0649, SA1023
119

1210
namespace CommunityToolkit.WinUI.Interop
@@ -21,26 +19,26 @@ internal unsafe struct IDispatcherQueue
2119
/// <summary>
2220
/// Native API for <see cref="DispatcherQueue.TryEnqueue(DispatcherQueueHandler)"/>.
2321
/// </summary>
24-
/// <param name="callback">A pointer to an <c>IDispatcherQueueHandler</c> object.</param>
22+
/// <param name="callback">A pointer to an <see cref="IDispatcherQueueHandler"/> object.</param>
2523
/// <param name="result">The result of the operation (the <see cref="bool"/> WinRT retval).</param>
2624
/// <returns>The HRESULT for the operation.</returns>
2725
[MethodImpl(MethodImplOptions.AggressiveInlining)]
28-
public int TryEnqueue(void* callback, byte* result)
26+
public int TryEnqueue(IDispatcherQueueHandler* callback, byte* result)
2927
{
30-
return ((delegate* unmanaged<IDispatcherQueue*, void*, byte*, int>)lpVtbl[7])((IDispatcherQueue*)Unsafe.AsPointer(ref this), callback, result);
28+
return ((delegate* unmanaged<IDispatcherQueue*, IDispatcherQueueHandler*, byte*, int>)lpVtbl[7])((IDispatcherQueue*)Unsafe.AsPointer(ref this), callback, result);
3129
}
3230

3331
/// <summary>
3432
/// Native API for <see cref="DispatcherQueue.TryEnqueue(DispatcherQueuePriority, DispatcherQueueHandler)"/>.
3533
/// </summary>
3634
/// <param name="priority">The priority for the input callback.</param>
37-
/// <param name="callback">A pointer to an <c>IDispatcherQueueHandler</c> object.</param>
35+
/// <param name="callback">A pointer to an <see cref="IDispatcherQueueHandler"/> object.</param>
3836
/// <param name="result">The result of the operation (the <see cref="bool"/> WinRT retval).</param>
3937
/// <returns>The HRESULT for the operation.</returns>
4038
[MethodImpl(MethodImplOptions.AggressiveInlining)]
41-
public int TryEnqueueWithPriority(DispatcherQueuePriority priority, void* callback, byte* result)
39+
public int TryEnqueueWithPriority(DispatcherQueuePriority priority, IDispatcherQueueHandler* callback, byte* result)
4240
{
43-
return ((delegate* unmanaged<IDispatcherQueue*, DispatcherQueuePriority, void*, byte*, int>)lpVtbl[8])((IDispatcherQueue*)Unsafe.AsPointer(ref this), priority, callback, result);
41+
return ((delegate* unmanaged<IDispatcherQueue*, DispatcherQueuePriority, IDispatcherQueueHandler*, byte*, int>)lpVtbl[8])((IDispatcherQueue*)Unsafe.AsPointer(ref this), priority, callback, result);
4442
}
4543
}
4644
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.CompilerServices;
6+
7+
#pragma warning disable CS0649, SA1023
8+
9+
namespace CommunityToolkit.WinUI.Interop
10+
{
11+
/// <summary>
12+
/// A struct mapping the native WinRT <c>IDispatcherQueueHandler</c> interface.
13+
/// </summary>
14+
internal unsafe struct IDispatcherQueueHandler
15+
{
16+
private readonly void** lpVtbl;
17+
18+
/// <summary>
19+
/// Native API for <c>IUnknown.Release()</c>.
20+
/// </summary>
21+
/// <returns>The updated reference count for the current instance.</returns>
22+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
23+
public uint Release()
24+
{
25+
return ((delegate* unmanaged<IDispatcherQueueHandler*, uint>)lpVtbl[2])((IDispatcherQueueHandler*)Unsafe.AsPointer(ref this));
26+
}
27+
}
28+
}

CommunityToolkit.WinUI/Extensions/Interop/Windows.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ internal static class Windows
2424
/// <summary>
2525
/// The GUID for the <c>IUnknown</c> COM interface.
2626
/// </summary>
27-
public static readonly Guid IUnknown = new(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
27+
public static readonly Guid GuidOfIUnknown = new(0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
2828

2929
/// <summary>
3030
/// The GUID for the <c>IAgileObject</c> WinRT interface.
3131
/// </summary>
32-
public static readonly Guid IAgileObject = new(0x94EA2B94, 0xE9CC, 0x49E0, 0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90);
32+
public static readonly Guid GuidOfIAgileObject = new(0x94EA2B94, 0xE9CC, 0x49E0, 0xC0, 0xFF, 0xEE, 0x64, 0xCA, 0x8F, 0x5B, 0x90);
3333

3434
/// <summary>
3535
/// The GUID for the <c>IDispatcherQueueHandler</c> WinRT interface.
3636
/// </summary>
37-
public static readonly Guid IDispatcherQueueHandler = new(0x2E0872A9, 0x4E29, 0x5F14, 0xB6, 0x88, 0xFB, 0x96, 0xD5, 0xF9, 0xD5, 0xF8);
37+
public static readonly Guid GuidOfIDispatcherQueueHandler = new(0x2E0872A9, 0x4E29, 0x5F14, 0xB6, 0x88, 0xFB, 0x96, 0xD5, 0xF9, 0xD5, 0xF8);
3838
}
3939
}

0 commit comments

Comments
 (0)