ARC, between block and C callback - objective-c

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.

Related

Why does this code leak instance of Sample class?

Any idea on why this code leaks (over-retains) instances of Sample class after [startSampling:action:] method is called on them? Profiler shows positive retain count after sampling is complete (i.e. sample() block returns YES). ARC is obviously enabled.
#implementation Sample
- (void)startSampling:(BOOL (^)(Sample *sender))sample action:(void (^)(Sample *sender))action {
__block void (^next)(Sample *sender) = nil;
void (^block)(Sample *sender) = ^(Sample *sender) {
if (sample(sender)) {
action(sender);
} else {
[self performBlock:next afterDelay:self.duration / 100.0];
}
};
next = block;
[self performBlock:block afterDelay:self.duration / 100.0];
}
#end
You're creating a block in that method. The block is essentially a struct with a field for each of the externally-defined variables used by the block, plus some extra stuff like a pointer to the code to be run for the block:
struct TheBlock {
void (*function)(TheBlock *);
// other bookkeeping fields
__strong TheBlock *next;
__strong OtherBlockType *sample;
__strong OtherBlockType *action;
__strong Sample *self;
};
When you do next = block;, you're setting that next field to point to the struct containing it. So the block retains itself, which is a retain cycle, preventing the block from being released. And the block also retains self, preventing the Sample instance from being released.
One way to fix it is to set next to nil when you're done with it:
void (^block)(Sample *sender) = ^(Sample *sender) {
if (sample(sender)) {
action(sender);
next = nil;
} else {
[self performBlock:next afterDelay:self.duration / 100.0];
}
};
That will break the retain cycle when the block is no longer needed, allowing the block and the Sample instance to be deallocated.
The variable next is captured by the block. Blocks retain any captured variables of object pointer type when copied (actually, since it's a variable of block pointer type, it is copied instead of retained). Under ARC, __block variables are retained too. next is set to point to the block, so the block has a strong reference to itself. That's why you have a retain cycle.
To fix it, you simply have to make next a weak reference:
__block __weak void (^next)(Sample *sender) = nil;

wrap c callbacks by blocks (__bridge_transfer and blocks)

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.

Objective-C pass block as parameter

How can I pass a Block to a Function/Method?
I tried - (void)someFunc:(__Block)someBlock with no avail.
ie. What is the type for a Block?
The type of a block varies depending on its arguments and its return type. In the general case, block types are declared the same way function pointer types are, but replacing the * with a ^. One way to pass a block to a method is as follows:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
But as you can see, that's messy. You can instead use a typedef to make block types cleaner:
typedef void (^ IteratorBlock)(id, int);
And then pass that block to a method like so:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
The easiest explanation for this question is follow these templates:
1. Block as a method parameter
Template
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
Example
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
Other use of cases:
2. Block as a Property
Template
#property (nonatomic, copy) returnType (^blockName)(parameters);
Example
#property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
3. Block as a method argument
Template
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
Example
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4. Block as a local variable
Template
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
Example
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5. Block as a typedef
Template
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
Example
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
This might be helpful:
- (void)someFunc:(void(^)(void))someBlock;
You can do like this, passing block as a block parameter:
//creating a block named "completion" that will take no arguments and will return void
void(^completion)() = ^() {
NSLog(#"bbb");
};
//creating a block namd "block" that will take a block as argument and will return void
void(^block)(void(^completion)()) = ^(void(^completion)()) {
NSLog(#"aaa");
completion();
};
//invoking block "block" with block "completion" as argument
block(completion);
One more way to pass block using с functions in example below.
I`ve created functions to perform anything in background and on main queue.
blocks.h file
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
blocks.m file
#import "blocks.h"
void performInBackground(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}
void performOnMainQueue(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_main_queue(), block);
}
Than import blocks.h when necessary and invoke it:
- (void)loadInBackground {
performInBackground(^{
NSLog(#"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
You also can set block as a simple property if it's applicable for you:
#property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
make sure that block property is "copy"!
and of course you can also use typedef:
typedef void (^SimpleBlock)(id);
#property (nonatomic, copy) SimpleBlock someActionHandler;
Also you invoke or call a block in using usual c function syntax
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
More info on blocks here
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxGettingStarted.html#//apple_ref/doc/uid/TP40007502-CH7-SW1
I always tend to forget about blocks syntax. This always comes to my mind when I need to declare a block. I hope it helps someone :)
http://fuckingblocksyntax.com
I wrote a completionBlock for a class which will return the values of dice after they have been shaken:
Define typedef with returnType (.h above #interface declaration)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
Define a #property for the block (.h)
#property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
Define a method with finishBlock (.h)
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
Insert previous defined method in .m file and commit finishBlock to #property defined before
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
To trigger completionBlock pass predefined variableType to it
(Don't forget to check whether the completionBlock exists)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}
Despite the answers given on this thread, I really struggled to write a function which would take a Block as a function - and with a parameter. Eventually, here's the solution I came up with.
I wanted to write a generic function, loadJSONthread, which would take the URL of a JSON Web Service, load some JSON data from this URL on a background thread, then return an NSArray* of results back to the calling function.
Basically, I wanted to keep all the background-thread complexity hidden away in a generic reuseable function.
Here's how I would call this function:
NSString* WebServiceURL = #"http://www.inorthwind.com/Service1.svc/getAllCustomers";
[JSONHelper loadJSONthread:WebServiceURL onLoadedData:^(NSArray *results) {
// Finished loading the JSON data
NSLog(#"Loaded %lu rows.", (unsigned long)results.count);
// Iterate through our array of Company records, and create/update the records in our SQLite database
for (NSDictionary *oneCompany in results)
{
// Do something with this Company record (eg store it in our SQLite database)
}
} ];
...and this is the bit I struggled with: how to declare it, and how to get it to call the Block function once the data was loaded, and pass the Block an NSArray* of records loaded:
+(void)loadJSONthread:(NSString*)urlString onLoadedData:(void (^)(NSArray*))onLoadedData
{
__block NSArray* results = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Call an external function to load the JSON data
NSDictionary * dictionary = [JSONHelper loadJSONDataFromURL:urlString];
results = [dictionary objectForKey:#"Results"];
dispatch_async(dispatch_get_main_queue(), ^{
// This code gets run on the main thread when the JSON has loaded
onLoadedData(results);
});
});
}
This StackOverflow question concerns how to call functions, passing a Block as a parameter, so I've simplified the code above, and not included the loadJSONDataFromURL function.
But, if you are interested, you can find a copy of this JSON loading function on this blog:
http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
Hope this helps some other XCode developers !
(Don't forget to vote up this question and my answer, if it does !)
The full template looks like
- (void) main {
//Call
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}
//Definition
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
//Execute a block
successBlock();
failureBlock([[NSError alloc]init]);
}
- (void) successMethod {
}
- (void) failureMethod:(NSError*) error {
}

Manual retain with ARC

Before ARC I had the following code that retains the delegate while an async operation is in progress:
- (void)startAsyncWork
{
[_delegate retain];
// calls executeAsyncWork asynchronously
}
- (void)executeAsyncWork
{
// when finished, calls stopAsyncWork
}
- (void)stopAsyncWork
{
[_delegate release];
}
What is the equivalent to this pattern with ARC?
I have occasionally needed to manually retain and release things (sometimes just for debugging) and came up with the following macros:
#define AntiARCRetain(...) void *retainedThing = (__bridge_retained void *)__VA_ARGS__; retainedThing = retainedThing
#define AntiARCRelease(...) void *retainedThing = (__bridge void *) __VA_ARGS__; id unretainedThing = (__bridge_transfer id)retainedThing; unretainedThing = nil
This works by using the __bridge_retained and __bridge_transfer to cast things to and from (void *) which causes things to be retained, or to create a strong reference without calling retain.
Have fun, but be careful!
Why not just assign your delegate object to a strong ivar for the duration of the asynchronous task?
Or have a local variable in executeAsyncWork
- (void)executeAsyncWork
{
id localCopy = _delegate;
if (localCopy != nil) // since this method is async, the delegate might have gone
{
// do work on local copy
}
}
Something like this:
- (void)startAsyncWork
{
id<YourProtocol> delegate = _delegate;
dispatch_async(/* some queue */, ^{
// do work
[delegate doSomething];
}
}
The block will retain the delegate as long as needed...

Can a C function be used as a selector in Cocoa?

I want to start a new thread using a C function, not an objective-C method. I tried
[NSThread detachNewThreadSelector: #selector(func) toTarget: nil withObject: id(data)];
where I have
void func(void *data) {
// ...
}
and data is a void *, but I get a runtime crash in objc_msgSend, called from
-[NSThread initWithTarget:selector:object:]
What can I do instead? Is it even possible?
Roll your own:
// In some .h file. #import to make the extension methods 'visible' to your code.
#interface NSThread (FunctionExtension)
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data;
-(id)initWithFunction:(void (*)(void *))function data:(void *)data;
#end
// In some .m file.
#implementation NSThread (FunctionExtension)
+(void)startBackgroundThreadUsingFunction:(id)object
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
void (*startThreadFunction)(void *) = (void (*)(void *))[[object objectForKey:#"function"] pointerValue];
void *startThreadData = (void *) [[object objectForKey:#"data"] pointerValue];
if(startThreadFunction != NULL) { startThreadFunction(startThreadData); }
[pool release];
pool = NULL;
}
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data
{
[[[[NSThread alloc] initWithFunction:function data:data] autorelease] start];
}
-(id)initWithFunction:(void (*)(void *))function data:(void *)data
{
return([self initWithTarget:[NSThread class] selector:#selector(startBackgroundThreadUsingFunction:) object:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:function], #"function", [NSValue valueWithPointer:data], #"data", NULL]]);
}
#end
NOTE: I wrote the above code and here by place it in the public domain. (sometimes the lawyers like this kind of stuff) It is also completely untested!
You can always remove the NSAutoreleasePool bits if you can guarantee that the thread entry function also creates one... but it's harmless, has no speed penalty what-so-ever, and makes calling arbitrary C functions that much more simpler. I'd say just keep it there.
And you can use it like so:
void bgThreadFunction(void *data)
{
NSLog(#"bgThreadFunction STARTING!! Data: %p", data);
}
-(void)someMethod
{
// init and then start later...
NSThread *bgThread = [[[NSThread alloc] initWithFunction:bgThreadFunction data:(void *)0xdeadbeef] autorelease];
// ... assume other code/stuff here.
[bgThread start];
// Or, use the all in one convenience method.
[NSThread detachNewThreadByCallingFunction:bgThreadFunction data:(void *)0xcafebabe];
}
When run:
2009-08-30 22:21:12.529 test[64146:1303] bgThreadFunction STARTING!! Data: 0xdeadbeef
2009-08-30 22:21:12.529 test[64146:2903] bgThreadFunction STARTING!! Data: 0xcafebabe
Create an Objective-C class with a method that simply calls that function. Take the selector of that method and pass it to NSThread API.
Well, I'm not sure if it's possible, but keep in mind that every Objective-C method has two implicit/hidden arguments, self and _cmd. An IMP is usually typedef'd like this:
typedef id (*IMP)(id,SEL,...);
If you want to jerry-rig methods and selectors, you need to have a method that looks like that:
void func (id self, SEL _cmd, void *firstParameter);
But even after that, you need to register a selector name with the runtime, then you need to associate that selector with the method, but this is done on a class-by-class basis (i.e. classes can have different implementations of the same selector name), so you at least need to have a dummy class.
It is much, much simpler just to create a dummy class and dummy instance of that class than call the various runtime API just to get NSThread to invoke a single C function.
If you don't need NSThread stuff, you can also start a thread with direct POSIX interface.
I want to start a new thread using a C function, not an objective-C method
Then why don't you just use:
POSIX threads,
GCD?
dispatch_async_f() (man) is suited exactly for this purpose.