The current pattern generated by the generator (and which we copy around liberally), goes something like this:
unsafe {
BlockLiteral *block_ptr_handler;
BlockLiteral block_handler;
block_handler = new BlockLiteral ();
block_ptr_handler = &block_handler;
block_handler.SetupBlockUnsafe (blockCallback, userCallback);
NativePInvoke ((void*) block_ptr_handler);
block_ptr_handler->CleanupBlock ();
}
I think we can make it possible to simplify this a lot, so that we get down to:
using (var block = new BlockLiteral (blockCallback, userCallback, false))
NativePInvoke (ref block);
This requires:
- Make
BlockLiteral implement IDisposable (and call CleanupBlock in Dispose).
- Add a
BlockLiteral constructor that takes the corresponding delegates.
- Add support to the linker/optimizer for the new
BlockLiteral constructor.
- Change P/Invokes to take
ref BlockLiteral instead of void * or IntPtr (this only works if the block isn't nullable).
Advantages
- Much smaller & simpler C# code.
- We won't leak the block if the P/Invoke (or any code after setting up the block) throws an exception.
Disadvantages
- I think we'd end up creating more compiled (both IL and native), because of the additional exception handling by the using statement. This would need to be confirmed by testing though.
The current pattern generated by the generator (and which we copy around liberally), goes something like this:
I think we can make it possible to simplify this a lot, so that we get down to:
This requires:
BlockLiteralimplementIDisposable(and callCleanupBlockinDispose).BlockLiteralconstructor that takes the corresponding delegates.BlockLiteralconstructor.ref BlockLiteralinstead ofvoid *orIntPtr(this only works if the block isn't nullable).Advantages
Disadvantages