Skip to content

Commit

Permalink
[runtime] Add support for keeping the same block alive multiple times.
Browse files Browse the repository at this point in the history
…Fixes dotnet#18161.

We can be asked to keep the same block+delegate pair alive multiple times, so
add support for keeping track how many times a block must be freed once the
corresponding delegate is collected by the GC.

Fixes dotnet#18161.
  • Loading branch information
rolfbjarne authored and vs-mobiletools-engineering-service2 committed May 19, 2023
1 parent 8587acb commit 0b13537
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
21 changes: 19 additions & 2 deletions src/ObjCRuntime/Blocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -564,10 +564,27 @@ unsafe internal static BlockLiteral CreateBlock (Action action)
}

// This class will free the specified block when it's collected by the GC.
internal class BlockCollector : TrampolineBlockBase {
internal class BlockCollector {
IntPtr block;
int count;
public BlockCollector (IntPtr block)
: base (block, owns: true)
{
this.block = block;
count = 1;
}

public void Add (IntPtr block)
{
if (block != this.block)
throw new InvalidOperationException (string.Format ("Can't release the block 0x{0} because this BlockCollector instance is already tracking 0x{1}.", block.ToString ("x"), this.block.ToString ("x")));
Interlocked.Increment (ref count);
}

~BlockCollector ()
{
for (var i = 0; i < count; i++)
Runtime.ReleaseBlockOnMainThread (block);
count = 0;
}
}
#endif
Expand Down
6 changes: 5 additions & 1 deletion src/ObjCRuntime/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2046,7 +2046,11 @@ static Delegate ReleaseBlockWhenDelegateIsCollected (IntPtr block, Delegate @del
if (block == IntPtr.Zero)
return @delegate;

block_lifetime_table.Add (@delegate, new BlockCollector (block));
if (block_lifetime_table.TryGetValue (@delegate, out var existingCollector)) {
existingCollector.Add (block);
} else {
block_lifetime_table.Add (@delegate, new BlockCollector (block));
}
return @delegate;
}

Expand Down

0 comments on commit 0b13537

Please sign in to comment.