wrap c callbacks by blocks (__bridge_transfer and blocks) - objective-c

I'm writing an Obj-C wrapper to a standard C API. I would like to replace C callbacks by blocks.
Let imagine a C API:
void my_async_function(void (* callback)(void *), void *udata);
The Obj-C wrapper looks like this:
- (void)myAsyncFunction:(dispatch_block_t)block
{
void *udata = (__bridge_retained void *)block;
my_async_function(my_callback, udata);
}
void my_callback(void *udata)
{
dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
block();
}
__bridge_retained and __bridge_transfer work well in many cases but on blocks, they result in a very strange behavior.
The assembly code of myAsyncFunction: has no retain at all (Xcode 4.4, ARC, O3).
What is very strange is that the following core, generates a objc_retainBlock, what I expected for myAsyncFunction:
void *a_global_var;
- (void)myAsyncFunction2:(dispatch_block_t)block
{
void *udata = (__bridge_retained void *)block;
a_global_var = udata;
my_async_function(my_callback, udata);
}
Can we call that a bug of the compiler?
If not, what rule the compiler is following?
Similar topics:
iOS: Block property directly set crashes when accessed
How to cast blocks to and from void *

Try:
- (void)myAsyncFunction:(dispatch_block_t)block
{
void *udata = (__bridge_transfer void *) [block copy];
my_async_function(my_callback, udata);
}
void my_callback(void *udata)
{
// however, see the comment in the last paragraph
dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
block();
}
Ordinarily, the compiler synthesizes in a Block_copy call when you assign a block pointer to a location where it could outlive the block structure it references.
However, the compiler has no way of knowing what happens to the void* after you pass it into the C api, and anyway you're overriding whatever the compiler might think it ought to do with the __bridge_retained call. Retaining a block when storing a reference isn't enough.
Also, even with this change, your callback must be called exactly once, as it's responsible for releasing the block. If it never gets called, you'll leak the block. If it gets called more than once, you'll crash. So you'll probably want to make instances of your wrapper class responsible for managing the memory of the block, unless the C api allows you to provide a cleanup function, which you could use to release the block.

Related

Objective-C define block after passing it to a method

Is it possible to define a block after passing it to a method? I want to do this so the code is in somewhat the order it runs in:
// Declare the block
void (^doStuffBlock)(void);
// Pass the block.
[self prepareToDoStuffWithCompletion:doStuffBlock];
// Define the block.
doStuffBlock = ^void() {
// Do stuff
};
doesn't work because inside prepareToDoStuffWithCompletion: the block doStuffBlock is nil.
you should first define the block then pass it to the method:
// Declare the block
void (^doStuffBlock)(void);
// Define the block.
doStuffBlock= ^void() {
// Do stuff
};
// Pass the block.
[self prepareToDoStuffWithCompletion:doStuffBlock];
You could use a typedef.
typedef void (^TypeName)(void);
- (void)bar:(TypeName)completion {
completion();
}
TypeName foo = ^() { /*...*/ };
[self bar:foo];
(My obj-c syntax might be a little rusty, but what you want to do is possible in both Objective-C and Swift.
https://stackoverflow.com/a/29580490/620197
http://goshdarnblocksyntax.com/
If you are certain that the method will run your doStuffBlock after you "define" it, what you could do is have your doStuffBlock capture a variable holding a second block with the real logic of what it should do. You can set the real-logic block after you create doStuffBlock, and you need to make sure that the variable holding the real-logic block is a __block variable, so that changes to the variable in the function scope are seen in the block scope.
__block void (^realLogicBlock)(void);
[self prepareToDoStuffWithCompletion:^{
if (realLogicBlock)
realLogicBlock();
}];
realLogicBlock = ^void() {
// Do stuff
};
You might have to be careful about retain cycles though -- if inside realLogicBlock, you capture a reference to self or to something that will reference the prepareToDoStuffWithCompletion: completion handler, you would have a retain cycle, in which case you may have to introduce a weak reference somewhere.
If you supply the completion handler closure, you are effectively saying “here is the closure I want you to use”.
If you are going to supply the closure later you would probably define a property:
#property (nonatomic, copy, nullable) void (^doStuff)(void);
Then, do not supply the closure when you call the method, but rather refer to this property:
- (void)prepareToDoStuff {
[self somethingAsynchronousWithCompletion:^{
if (self.doStuff) {
self.doStuff();
// if completion handler, you’d often release it when done, e.g.
//
// self.doStuff = nil;
}
}];
}
And, then you can call this method and supply the closure later:
[self prepareToDoStuff];
self.doStuff = ^{
NSLog(#"do stuff done");
};
A few additional considerations:
Make sure you synchronize your access to this doStuff property. E.g., in the above, I am assuming that the somethingAsynchronousWithCompletion is calling its completion handler on the main thread. If not, synchronize your access (like you would any non-thread-safe property in a multithreaded environment).
There is a logical race if you first call the method that will eventually call the block, and only later set that block property. Sometimes that is perfectly fine (e.g. maybe you are just trying to specify what UI to update when the asynchronous process finishes). Other times, the race can bite you. It depends upon the functional intent of the block property.
I would give the block property a name that better reflects its functional purpose (e.g. completionHandler or notificationHandler or didReceiveValue or whatever).

ARC, between block and C callback

I've a c function which takes a callback function as one parameter, I'm going to write an Obj-C wrapper to a standard C API. I would like to replace C callbacks by blocks.
Let's imagine a C API:
void audioStopFunction(void (*callback)(void *), void *udata);
The Obj-C wrapper looks like this:
- (void)myAudioStopFunction:(dispatch_block_t)block
{
void *udata = (__bridge void *)block;
audioStopFunction(my_callback, udata);
}
void my_callback(void *udata)
{
dispatch_block_t block = (__bridge_transfer dispatch_block_t)udata;
block();
}
Now, I have some questions:
In myAudioStopFunction function, do i need to copy the block like below:
void *udata = (__bridge void *)[block copy];
In my_callback function, should i use __bridge instead of __bridge_transfer? And also, do i need to call Block_release after block()?
Will the code cause memory leak? if yes, then what's the correct way?
As the C callback is managed by the wrapper class it's most easy to let the class manage the ownership of the block. (I'm calling the block completionBlock, as this seems to be a bit more in line with Cocoa naming conventions.)
#interface AudioCallbackWrapper
#property (nonatomic) dispatch_block_t completionBlock;
#end
static void my_callback(void *udata)
{
dispatch_block_t block = (__bridge dispatch_block_t)udata;
if (block != nil)
block();
}
#implementation AudioCallbackWrapper
- (void)setCompletionBlock:(dispatch_block_t)completionBlock
{
_completionBlock = [completionBlock copy];
audioStopFunction(my_callback, (__bridge void *)_completionBlock);
}
- (void)dealloc
{
// remove the C callback before completionBlock is released
self.completionBlock = nil;
}
#end
Since the block's lifetime is managed by the enclosing wrapper, the C code never has to transfer ownership. So the code only contains __bridge casts to and from a void *.
Will the code cause memory leak? if yes, then what's the correct way?
Your original code would release the block every time the callback fires. The block pointer would dangle after the first callback.

Running a nil block in Objective C [duplicate]

I started using blocks a lot and soon noticed that nil blocks cause bus errors:
typedef void (^SimpleBlock)(void);
SimpleBlock aBlock = nil;
aBlock(); // bus error
This seems to go against the usual behaviour of Objective-C that ignores messages to nil objects:
NSArray *foo = nil;
NSLog(#"%i", [foo count]); // runs fine
Therefore I have to resort to the usual nil check before I use a block:
if (aBlock != nil)
aBlock();
Or use dummy blocks:
aBlock = ^{};
aBlock(); // runs fine
Is there another option? Is there a reason why nil blocks couldn’t be simply a nop?
I'd like to explain this a bit more, with a more complete answer. First let's consider this code:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
void (^block)() = nil;
block();
}
If you run this then you'll see a crash on the block() line that looks something like this (when run on a 32-bit architecture - that's important):
EXC_BAD_ACCESS (code=2, address=0xc)
So, why is that? Well, the 0xc is the most important bit. The crash means that the processor has tried to read the information at memory address 0xc. This is almost definitely an entirely incorrect thing to do. It's unlikely there's anything there. But why did it try to read this memory location? Well, it's due to the way in which a block is actually constructed under the hood.
When a block is defined, the compiler actually creates a structure on the stack, of this form:
struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};
The block is then a pointer to this structure. The fourth member, invoke, of this structure is the interesting one. It is a function pointer, pointing to the code where the block's implementation is held. So the processor tries to jump to that code when a block is invoked. Notice that if you count the number of bytes in the structure before the invoke member, you'll find that there are 12 in decimal, or C in hexadecimal.
So when a block is invoked, the processor takes the address of the block, adds 12 and tries to load the value held at that memory address. It then tries to jump to that address. But if the block is nil then it'll try to read the address 0xc. This is a duff address, clearly, and so we get the segmentation fault.
Now the reason it must be a crash like this rather than silently failing like an Objective-C message call does is really a design choice. Since the compiler is doing the work of deciding how to invoke the block, it would have to inject nil checking code everywhere a block is invoked. This would increase code size and lead to bad performance. Another option would be to use a trampoline which does the nil checking. However this would also incur performance penalty. Objective-C messages already go through a trampoline since they need to look up the method that will actually be invoked. The runtime allows for lazy injection of methods and changing of method implementations, so it's already going through a trampoline anyway. The extra penalty of doing the nil checking is not significant in this case.
For more information, see my blog posts.
Matt Galloway's answer is perfect! Great read!
I just want to add that there are some ways to make life easier. You could define a macro like this:
#define BLOCK_SAFE_RUN(block, ...) block ? block(__VA_ARGS__) : nil
It can take 0 – n arguments. Example of usage
typedef void (^SimpleBlock)(void);
SimpleBlock simpleNilBlock = nil;
SimpleBlock simpleLogBlock = ^{ NSLog(#"working"); };
BLOCK_SAFE_RUN(simpleNilBlock);
BLOCK_SAFE_RUN(simpleLogBlock);
typedef void (^BlockWithArguments)(BOOL arg1, NSString *arg2);
BlockWithArguments argumentsNilBlock = nil;
BlockWithArguments argumentsLogBlock = ^(BOOL arg1, NSString *arg2) { NSLog(#"%#", arg2); };
BLOCK_SAFE_RUN(argumentsNilBlock, YES, #"ok");
BLOCK_SAFE_RUN(argumentsLogBlock, YES, #"ok");
If you want to get the return value of the block and you are not sure if the block exists or not then you are probably better off just typing:
block ? block() : nil;
This way you can easily define the fallback value. In my example 'nil'.
Caveat: I'm no expert in Blocks.
Blocks are objective-c objects but calling a block is not a message, although you could still try [block retain]ing a nil block or other messages.
Hopefully, that (and the links) helps.
This is my simple nicest solution… Maybe there is possible to write one universal run function with those c var-args but I don’t know how to write that.
void run(void (^block)()) {
if (block)block();
}
void runWith(void (^block)(id), id value) {
if (block)block(value);
}

OS X: How to correctly bridge release pointer with __bridge_transfer

I have a block object that is converted to a void * pointer to pass to a C library. I'm deploying to OS X 10.6 so CFBridgingRetain and CFBridgingRelease are not available.
Instead I'm doing:
void ptr_retain(void (^block)()) {
void *ptr = (__bridge_retained void *)(block);
...
// pass ptr to C lib
}
void ptr_release(const void *ptr) {
// C lib calls this function
void (^block)() = (__bridge_transfer void(^)())ptr;
}
Question:
In ptr_release I get an "unused variable" warning. I'm concerned the compiler may optimize out the __bridge_transfer line and the block will never be released. Could this happen? Even if it doesn't, is this the correct way to let ARC know to release the block at the end of ptr_release?
When you use __bridge_retained or CFBridgingRetain(), you get a pointer with a +1 retain count. You are responsible for releasing this reference.
You can release the reference by transferring ownership back to ARC (using __bridge_transfer or CFBridgingRelease()), or you can simply call CFRelease().
In your case, just use CFRelease():
void ptr_release(const void *ptr) {
CFRelease((CFTypeRef)ptr);
}

Is there a SELF pointer for blocks?

I'd like to recursively call a block from within itself. In an obj-c object, we get to use "self", is there something like this to refer to a block instance from inside itself?
Fun story! Blocks actually are Objective-C objects. That said, there is no exposed API to get the self pointer of blocks.
However, if you declare blocks before using them, you can use them recursively. In a non-garbage-collected environment, you would do something like this:
__weak __block int (^block_self)(int);
int (^fibonacci)(int) = [^(int n) {
if (n < 2) { return 1; }
return block_self(n - 1) + block_self(n - 2);
} copy];
block_self = fibonacci;
It is necessary to apply the __block modifier to block_self, because otherwise, the block_self reference inside fibonacci would refer to it before it is assigned (crashing your program on the first recursive call). The __weak is to ensure that the block doesn't capture a strong reference to itself, which would cause a memory leak.
The following recursive block code will compile and run using ARC, GC, or manual memory management, without crashing, leaking, or issuing warnings (analyzer or regular):
typedef void (^CountdownBlock)(int currentValue);
- (CountdownBlock) makeRecursiveBlock
{
CountdownBlock aBlock;
__block __unsafe_unretained CountdownBlock aBlock_recursive;
aBlock_recursive = aBlock = [^(int currentValue)
{
if(currentValue >= 0)
{
NSLog(#"Current value = %d", currentValue);
aBlock_recursive(currentValue-1);
}
} copy];
#if !__has_feature(objc_arc)
[aBlock autorelease];
#endif
return aBlock;
}
- (void) callRecursiveBlock
{
CountdownBlock aBlock = [self makeRecursiveBlock];
// You don't need to dispatch; I'm doing this to demonstrate
// calling from beyond the current autorelease pool.
dispatch_async(dispatch_get_main_queue(), ^
{
aBlock(10);
});
}
Important considerations:
You must copy the block onto the heap manually or else it will try to access a nonexistent stack when you call it from another context (ARC usually does this for you, but not in all cases. Better to play it safe).
You need TWO references: One to hold the strong reference to the block, and one to hold a weak reference for the recursive block to call (technically, this is only needed for ARC).
You must use the __block qualifier so that the block doesn't capture the as-yet unassigned value of the block reference.
If you're doing manual memory management, you'll need to autorelease the copied block yourself.
You have to declare the block variable as __block:
typedef void (^MyBlock)(id);
__block MyBlock block = ^(id param) {
NSLog(#"%#", param);
block(param);
};
There is no self for blocks (yet). You can build one like this (assuming ARC):
__block void (__weak ^blockSelf)(void);
void (^block)(void) = [^{
// Use blockSelf here
} copy];
blockSelf = block;
// Use block here
The __block is needed so we can set blockSelf to the block after creating the block. The __weak is needed because otherwise the block would hold a strong reference to itself, which would cause a strong reference cycle and therefore a memory leak. The copy is needed to make sure that the block is copied to the heap. That may be unnecessary with newer compiler versions, but it won't do any harm.