@@ -9,6 +9,8 @@ public static class Marshalling
9
9
{
10
10
internal static readonly Dictionary < Delegate , JitCallback ? > CachedDelegates = new ( ) ;
11
11
internal static readonly Dictionary < nint , Delegate > CachedFunctions = new ( ) ;
12
+ private static readonly Mutex MutexDelegates = new ( ) ;
13
+ private static readonly Mutex MutexFunctions = new ( ) ;
12
14
13
15
internal static unsafe object ? [ ] ? MarshalParameterArray ( nint paramsPtr , int parameterCount , MethodBase methodInfo )
14
16
{
@@ -547,28 +549,38 @@ internal static void MarshalFieldAddress(object obj, FieldInfo fieldInfo, nint o
547
549
548
550
public static Delegate GetDelegateForFunctionPointer( nint funcAddress , Type ? delegateType )
549
551
{
550
- if ( CachedFunctions . TryGetValue ( funcAddress , out var d) )
551
- {
552
- return d ;
553
- }
552
+ MutexFunctions . WaitOne ( ) ;
554
553
555
- if ( delegateType = = null )
554
+ try
556
555
{
557
- throw new Exception ( "Type required to properly generate delegate at runtime") ;
558
- }
556
+ if ( CachedFunctions . TryGetValue ( funcAddress , out var d) )
557
+ {
558
+ return d ;
559
+ }
559
560
560
- MethodInfo methodInfo = delegateType . GetMethod ( "Invoke ") ! ;
561
- if ( IsNeedMarshal( methodInfo. ReturnType) || methodInfo. GetParameters( ) . Any( p => IsNeedMarshal( p . ParameterType ) ) )
562
- {
563
- d = MethodUtils . CreateObjectArrayDelegate ( delegateType , ExternalInvoke ( funcAddress , methodInfo ) ) ;
561
+ if ( delegateType = = null )
562
+ {
563
+ throw new Exception ( "Type required to properly generate delegate at runtime") ;
564
+ }
565
+
566
+ MethodInfo methodInfo = delegateType . GetMethod ( "Invoke ") ! ;
567
+ if ( IsNeedMarshal( methodInfo. ReturnType) ||
568
+ methodInfo. GetParameters( ) . Any( p => IsNeedMarshal( p . ParameterType ) ) )
569
+ {
570
+ d = MethodUtils . CreateObjectArrayDelegate ( delegateType , ExternalInvoke ( funcAddress , methodInfo ) ) ;
571
+ }
572
+ else
573
+ {
574
+ d = Marshal . GetDelegateForFunctionPointer ( funcAddress , delegateType ) ;
575
+ }
576
+
577
+ CachedFunctions . Add ( funcAddress , d ) ;
578
+ return d ;
564
579
}
565
- else
580
+ finally
566
581
{
567
- d = Marshal . GetDelegateForFunctionPointer ( funcAddress , delegateType ) ;
582
+ MutexFunctions . ReleaseMutex ( ) ;
568
583
}
569
-
570
- CachedFunctions . Add ( funcAddress , d ) ;
571
- return d ;
572
584
}
573
585
574
586
private static unsafe nint RCast < T > ( T primitive) where T : struct
@@ -1564,29 +1576,39 @@ private static unsafe void DestroyStorage((nint, ValueType)* handlers, int count
1564
1576
1565
1577
public static nint GetFunctionPointerForDelegate ( Delegate d )
1566
1578
{
1567
- if ( CachedDelegates . TryGetValue ( d , out var callback) )
1568
- {
1569
- return callback ? . Function ?? Marshal . GetFunctionPointerForDelegate ( d ) ;
1570
- }
1579
+ MutexDelegates . WaitOne ( ) ;
1571
1580
1572
- MethodInfo methodInfo = d . Method ;
1573
- if ( IsNeedMarshal ( methodInfo . ReturnType ) || methodInfo . GetParameters ( ) . Any ( p => IsNeedMarshal ( p . ParameterType ) ) )
1581
+ try
1574
1582
{
1575
- callback = new JitCallback( d) ;
1583
+ if ( CachedDelegates . TryGetValue ( d , out var callback) )
1584
+ {
1585
+ return callback ? . Function ?? Marshal . GetFunctionPointerForDelegate ( d ) ;
1586
+ }
1576
1587
1577
- nint function = callback. Function;
1578
- if ( function = = nint . Zero )
1588
+ MethodInfo methodInfo = d . Method ;
1589
+ if ( IsNeedMarshal ( methodInfo . ReturnType ) ||
1590
+ methodInfo . GetParameters ( ) . Any ( p => IsNeedMarshal ( p . ParameterType ) ) )
1579
1591
{
1580
- throw new InvalidOperationException( $"{ methodInfo. Name} ( jit error: { callback. Error} ) ") ;
1592
+ callback = new JitCallback( d) ;
1593
+
1594
+ nint function = callback. Function;
1595
+ if ( function = = nint . Zero )
1596
+ {
1597
+ throw new InvalidOperationException( $"{ methodInfo. Name} ( jit error: { callback. Error} ) ") ;
1598
+ }
1599
+
1600
+ CachedDelegates . Add ( d , callback ) ;
1601
+ return function ;
1581
1602
}
1582
-
1583
- CachedDelegates . Add ( d , callback ) ;
1584
- return function ;
1585
- }
1586
1603
1587
- // We must manually keep the delegate from being collected by the garbage collector from managed code.
1588
- CachedDelegates . Add( d , null ) ;
1589
- return Marshal . GetFunctionPointerForDelegate ( d ) ;
1604
+ // We must manually keep the delegate from being collected by the garbage collector from managed code.
1605
+ CachedDelegates . Add( d , null ) ;
1606
+ return Marshal . GetFunctionPointerForDelegate ( d ) ;
1607
+ }
1608
+ finally
1609
+ {
1610
+ MutexDelegates . ReleaseMutex ( ) ;
1611
+ }
1590
1612
}
1591
1613
1592
1614
private static bool IsNeedMarshal ( Type paramType )
0 commit comments