Skip to content

Commit 5379671

Browse files
TautvydasZilysJosh Peterson
authored andcommitted
Fallback to runtime implemented OS specific synchronization context if none is set.
1 parent c1e3128 commit 5379671

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
@@ -297,6 +297,11 @@ private static SynchronizationContext GetThreadLocalContext()
297297
context = AndroidPlatform.GetDefaultSyncContext ();
298298
#endif
299299

300+
#if UNITY_AOT
301+
if (context == null)
302+
context = OSSpecificSynchronizationContext.Get();
303+
#endif
304+
300305
return context;
301306
}
302307

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

0 commit comments

Comments
 (0)