Skip to content

Commit 70de850

Browse files
authored
[runtime] Add support for keeping the same block alive multiple times. Fixes #18161. (#18277)
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 #18161.
1 parent aec2af3 commit 70de850

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

src/ObjCRuntime/Blocks.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,27 @@ unsafe internal static BlockLiteral CreateBlock (Action action)
564564
}
565565

566566
// This class will free the specified block when it's collected by the GC.
567-
internal class BlockCollector : TrampolineBlockBase {
567+
internal class BlockCollector {
568+
IntPtr block;
569+
int count;
568570
public BlockCollector (IntPtr block)
569-
: base (block, owns: true)
570571
{
572+
this.block = block;
573+
count = 1;
574+
}
575+
576+
public void Add (IntPtr block)
577+
{
578+
if (block != this.block)
579+
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")));
580+
Interlocked.Increment (ref count);
581+
}
582+
583+
~BlockCollector ()
584+
{
585+
for (var i = 0; i < count; i++)
586+
Runtime.ReleaseBlockOnMainThread (block);
587+
count = 0;
571588
}
572589
}
573590
#endif

src/ObjCRuntime/Runtime.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2055,7 +2055,11 @@ static Delegate ReleaseBlockWhenDelegateIsCollected (IntPtr block, Delegate @del
20552055
if (block == IntPtr.Zero)
20562056
return @delegate;
20572057

2058-
block_lifetime_table.Add (@delegate, new BlockCollector (block));
2058+
if (block_lifetime_table.TryGetValue (@delegate, out var existingCollector)) {
2059+
existingCollector.Add (block);
2060+
} else {
2061+
block_lifetime_table.Add (@delegate, new BlockCollector (block));
2062+
}
20592063
return @delegate;
20602064
}
20612065

0 commit comments

Comments
 (0)