Skip to content

Commit 5000ae3

Browse files
Fallback to runtime implemented OS specific synchronization context if none is set.
1 parent acf432a commit 5000ae3

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ private static SynchronizationContext GetThreadLocalContext()
293293
context = AndroidPlatform.GetDefaultSyncContext ();
294294
#endif
295295

296+
#if UNITY_AOT
297+
if (context == null)
298+
context = OSSpecificSynchronizationContext.Get();
299+
#endif
300+
296301
return context;
297302
}
298303

@@ -371,4 +376,86 @@ private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, In
371376
}
372377
#endif
373378
}
379+
380+
#if UNITY_AOT
381+
class OSSpecificSynchronizationContext : SynchronizationContext
382+
{
383+
object m_OSSynchronizationContext;
384+
private static readonly ConditionalWeakTable<object, OSSpecificSynchronizationContext> s_ContextCache = new ConditionalWeakTable<object, OSSpecificSynchronizationContext>();
385+
386+
private OSSpecificSynchronizationContext(object osContext)
387+
{
388+
m_OSSynchronizationContext = osContext;
389+
}
390+
391+
public static OSSpecificSynchronizationContext Get()
392+
{
393+
var osContext = GetOSContext();
394+
if (osContext == null)
395+
return null;
396+
397+
return s_ContextCache.GetValue(osContext, _osContext => new OSSpecificSynchronizationContext(_osContext));
398+
}
399+
400+
public override SynchronizationContext CreateCopy()
401+
{
402+
return new OSSpecificSynchronizationContext(m_OSSynchronizationContext);
403+
}
404+
405+
public override void Send(SendOrPostCallback d, object state)
406+
{
407+
throw new NotSupportedException();
408+
}
409+
410+
public override void Post(SendOrPostCallback d, object state)
411+
{
412+
var callback = Marshal.GetFunctionPointerForDelegate((InvocationEntryDelegate)InvocationEntry);
413+
var invocationContext = new InvocationContext(d, state);
414+
var invocationContextHandle = GCHandle.Alloc(invocationContext);
415+
PostInternal(m_OSSynchronizationContext, callback, GCHandle.ToIntPtr(invocationContextHandle));
416+
}
417+
418+
private delegate void InvocationEntryDelegate(IntPtr arg);
419+
420+
[MonoPInvokeCallback(typeof(InvocationEntryDelegate))]
421+
private static void InvocationEntry(IntPtr arg)
422+
{
423+
var invocationContextHandle = GCHandle.FromIntPtr(arg);
424+
var invocationContext = (InvocationContext)invocationContextHandle.Target;
425+
invocationContextHandle.Free();
426+
invocationContext.Invoke();
427+
}
428+
429+
[AttributeUsage (AttributeTargets.Method)]
430+
sealed class MonoPInvokeCallbackAttribute : Attribute
431+
{
432+
public MonoPInvokeCallbackAttribute(Type t)
433+
{
434+
}
435+
}
436+
437+
class InvocationContext
438+
{
439+
private SendOrPostCallback m_Delegate;
440+
private object m_State;
441+
442+
public InvocationContext(SendOrPostCallback d, object state)
443+
{
444+
m_Delegate = d;
445+
m_State = state;
446+
}
447+
448+
public void Invoke()
449+
{
450+
m_Delegate(m_State);
451+
}
452+
}
453+
454+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
455+
private extern static object GetOSContext();
456+
457+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
458+
private extern static void PostInternal(object osSynchronizationContext, IntPtr callback, IntPtr arg);
459+
}
460+
#endif
374461
}

0 commit comments

Comments
 (0)