-
Notifications
You must be signed in to change notification settings - Fork 568
Drop global Instance of JavaMarshalValueManager #11524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -187,7 +187,11 @@ internal static JniRuntime.JniValueManager CreateValueManager () | |
| return new AndroidValueManager (); | ||
| } | ||
|
|
||
| if (RuntimeFeature.IsCoreClrRuntime || RuntimeFeature.IsNativeAotRuntime) { | ||
| if (RuntimeFeature.IsCoreClrRuntime) { | ||
| return new JavaMarshalValueManager (); | ||
| } | ||
|
|
||
| if (RuntimeFeature.IsNativeAotRuntime) { | ||
| return new JavaMarshalValueManager (); | ||
|
Comment on lines
+190
to
195
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 💡 Code organization — These two branches have identical bodies. Unless there's a planned divergence (different Rule: Remove unused code / YAGNI |
||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,18 +27,11 @@ class JavaMarshalValueManager : JniRuntime.JniValueManager | |
|
|
||
| bool disposed; | ||
|
|
||
| static JavaMarshalValueManager? s_instance; | ||
|
|
||
| public static JavaMarshalValueManager Instance => | ||
| s_instance ?? throw new InvalidOperationException ("JavaMarshalValueManager has not been initialized. Call the constructor first."); | ||
|
|
||
| unsafe internal JavaMarshalValueManager () | ||
| public unsafe JavaMarshalValueManager () | ||
| { | ||
| var previous = Interlocked.CompareExchange (ref s_instance, this, null); | ||
| Debug.Assert (previous is null, "JavaMarshalValueManager must only be created once."); | ||
|
|
||
| // There can only be one instance because JavaMarshal.Initialize can only be called once. | ||
| var mark_cross_references_ftn = RuntimeNativeMethods.clr_initialize_gc_bridge (&BridgeProcessingStarted, &BridgeProcessingFinished); | ||
| var javaMarshalValueManagerHandle = new GCHandle<JavaMarshalValueManager> (this); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 Since there's only ever one Rule: Resource management (Postmortem
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the same as before, we could do this in |
||
| var mark_cross_references_ftn = RuntimeNativeMethods.clr_initialize_gc_bridge ( | ||
| GCHandle<JavaMarshalValueManager>.ToIntPtr (javaMarshalValueManagerHandle), &BridgeProcessingStarted, &BridgeProcessingFinished); | ||
| JavaMarshal.Initialize (mark_cross_references_ftn); | ||
| } | ||
|
|
||
|
|
@@ -356,6 +349,12 @@ public static GCHandle GetAssociatedGCHandle (HandleContext* context) | |
|
|
||
| public static unsafe void EnsureAllContextsAreOurs (MarkCrossReferencesArgs* mcr) | ||
| { | ||
| // This call site is reachable on all platforms. 'MarkCrossReferencesArgs.ComponentCount' is only supported on: 'android'. | ||
| // This call site is reachable on all platforms. 'MarkCrossReferencesArgs.Components' is only supported on: 'android'. | ||
| // This call site is reachable on all platforms. 'StronglyConnectedComponent.Count' is only supported on: 'android'. | ||
| // This call site is reachable on all platforms. 'StronglyConnectedComponent.Contexts' is only supported on: 'android'. | ||
| #pragma warning disable CA1416 | ||
|
|
||
| lock (referenceTrackingHandles) { | ||
| for (nuint i = 0; i < mcr->ComponentCount; i++) { | ||
| StronglyConnectedComponent component = mcr->Components [i]; | ||
|
|
@@ -375,7 +374,9 @@ static void EnsureContextIsOurs (IntPtr context) | |
| if (!referenceTrackingHandles.ContainsKey (context)) { | ||
| throw new InvalidOperationException ("Unknown reference tracking handle."); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #pragma warning restore CA1416 | ||
| } | ||
|
|
||
| public static HandleContext* Alloc (IJavaPeerable peer) | ||
|
|
@@ -422,20 +423,32 @@ static unsafe void BridgeProcessingStarted (MarkCrossReferencesArgs* mcr) | |
| } | ||
|
|
||
| [UnmanagedCallersOnly] | ||
| static unsafe void BridgeProcessingFinished (MarkCrossReferencesArgs* mcr) | ||
| static unsafe void BridgeProcessingFinished (IntPtr javaMarshalValueManagerHandle, MarkCrossReferencesArgs* mcr) | ||
| { | ||
| if (mcr == null) { | ||
| throw new ArgumentNullException (nameof (mcr), "MarkCrossReferencesArgs should never be null."); | ||
| } | ||
|
|
||
| ReadOnlySpan<GCHandle> handlesToFree = ProcessCollectedContexts (mcr); | ||
| JavaMarshalValueManager instance = GCHandle<JavaMarshalValueManager>.FromIntPtr (javaMarshalValueManagerHandle).Target; | ||
|
|
||
| ReadOnlySpan<GCHandle> handlesToFree = instance.ProcessCollectedContexts (mcr); | ||
|
|
||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 💡 Formatting — Extra blank line here (two consecutive blank lines). Rule: Minimal diffs |
||
| // This call site is reachable on all platforms. 'JavaMarshal.FinishCrossReferenceProcessing(MarkCrossReferencesArgs*, ReadOnlySpan<GCHandle>)' is only supported on: 'android'. | ||
| #pragma warning disable CA1416 | ||
| JavaMarshal.FinishCrossReferenceProcessing (mcr, handlesToFree); | ||
| #pragma warning restore CA1416 | ||
| } | ||
|
|
||
| static unsafe ReadOnlySpan<GCHandle> ProcessCollectedContexts (MarkCrossReferencesArgs* mcr) | ||
| unsafe ReadOnlySpan<GCHandle> ProcessCollectedContexts (MarkCrossReferencesArgs* mcr) | ||
| { | ||
| List<GCHandle> handlesToFree = []; | ||
| JavaMarshalValueManager instance = Instance; | ||
|
|
||
| // This call site is reachable on all platforms. 'MarkCrossReferencesArgs.ComponentCount' is only supported on: 'android'. | ||
| // This call site is reachable on all platforms. 'MarkCrossReferencesArgs.Components' is only supported on: 'android'. | ||
| // This call site is reachable on all platforms. 'StronglyConnectedComponent.Count' is only supported on: 'android'. | ||
| // This call site is reachable on all platforms. 'StronglyConnectedComponent.Contexts' is only supported on: 'android'. | ||
| #pragma warning disable CA1416 | ||
|
|
||
| for (int i = 0; (nuint)i < mcr->ComponentCount; i++) { | ||
| StronglyConnectedComponent component = mcr->Components [i]; | ||
|
|
@@ -444,6 +457,8 @@ static unsafe ReadOnlySpan<GCHandle> ProcessCollectedContexts (MarkCrossReferenc | |
| } | ||
| } | ||
|
|
||
| #pragma warning restore CA1416 | ||
|
|
||
| void ProcessContext (HandleContext* context) | ||
| { | ||
| if (context == null) { | ||
|
|
@@ -460,7 +475,7 @@ void ProcessContext (HandleContext* context) | |
| // Note: modifying the RegisteredInstances dictionary while processing the collected contexts | ||
| // is tricky and can lead to deadlocks, so we remember which contexts were collected and we will free | ||
| // them later outside of the bridge processing loop. | ||
| instance.CollectedContexts.Enqueue ((IntPtr)context); | ||
| CollectedContexts.Enqueue ((IntPtr)context); | ||
|
|
||
| // important: we must not free the handle before passing it to JavaMarshal.FinishCrossReferenceProcessing | ||
| handlesToFree.Add (handle); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.