Is there a SELF pointer for blocks? - objective-c

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.

Related

Storing blocks in a c-style array

I am trying to dynamically instantiate a c array of blocks, load it and then run them and could use some help.
// Definitions ===========================================
typedef void (^MorphC)(ScratchC* scratch);
#property (nonatomic) MorphC __strong * morphCs;
// Building up the Morph Registry ========================
static NSMutableDictionary* morphs_;
+ (void) initialize {
morphs_ = [[NSMutableDictionary alloc] init];
[MathC hydrate];
}
+ (void) hydrate {
[MathC registerMorph:#"sin" execute:^(ScratchC* scratch) {
AEScratchPush(scratch, sin(AEScratchPop(scratch)));
}];
}
+ (void) registerMorph:(NSString*)name execute:(MorphC)execute {
[morphs_ setObject:execute forKey:name];
}
+ (MorphC) morphFromKey:(NSString*)key {
return [morphs_ objectForKey:key];
}
// Loading up a temporary NSMutableArray* _compiling =====
- (void) applyTag:(NSString*)tag stack:(Stack*)stack {
[_compiling addObject:[MathC morphFromKey:tag]];
}
// Initializing C Array and loading from NSMutableArray ==
- (void) build {
_morphCs = (MorphC __strong *)malloc(_compiling.count*sizeof(MorphC));
i = 0;
for (MorphC morph in _compiling)
_morphCs[i++] = morph; // Currently, getting a bad ACCESS here
}
// Executing the Morphs ==================================
- (CGFloat) evaluateFloat:(VarsC*)vars {
if (![_morphs count]) return NAN;
AEScratchLoadVariables(_scratch, vars);
for (int i=0;i<[_morphs count];i++)
_morphCs[i](_scratch);
return AEScratchPop(_scratch);
}
I'm currently getting a EXC_BAD_ACCESS while building up the C Array, but I suspect I have a number of issues. I don't totally understand the need for the __strong at the morphCs definition, but the compiler complains with out. Should the property have a strong indicator also?
Do I need to be doing [morph copy] in one or more places?
Is there anything else I'm messing up?
You can't malloc an array of strong pointers.
Think about the semantics of a strong pointer: When it is declared, it's value is initialized to nil. When the variable goes out of scope, it releases its existing value. Therefore, the compiler must be able to keep track of strong pointers to be able to carry this out. If you have an array of strong pointers of unknown length, when it goes out of scope for example, how can the compiler know how many pointers to release? It can't.
In C++ terminology, strong references are "non-POD" types - they have nontrivial constructors and destructors. Therefore, they cannot be allocated with malloc.
It is mentioned here in the ARC specification:
It is undefined behavior if a managed operation is performed on a
__strong or __weak object without a guarantee that it contains a primitive zero bit-pattern, or if the storage for such an object is
freed or reused without the object being first assigned a null
pointer.
In other words, the only way you can use malloc and free is if you guarantee that every time after you call malloc you zero the memory of all the pointers you allocated, before using them. And every time before free you guarantee to first assign nil to each strong pointer in the array.
However, in Objective-C++, you can use new[] and delete[] to dynamically allocate arrays of strong pointers.
These requirements are followed automatically in Objective-C++ when
creating objects of retainable object owner type with new or new[] and
destroying them with delete, delete[], or a pseudo-destructor
expression.

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;

Add code to block dynamically

I'm pretty new to using blocks. I'm wondering if there is a way to add code dynamically to a block? A mutable block if you will.
This is not quite what it sounds like you want, but it achieves a similar result if not quite the same one: Having a __block NSMutableArray of blocks to be called sequentially from within an outer block.
A silly demo:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
__block NSMutableArray *subblocks = [NSMutableArray array];
void (^blockWithBlocks)(void) = ^{
NSLog(#"%s: in blockWithBlocks()", __PRETTY_FUNCTION__);
for (void (^subblock)(void) in subblocks) {
subblock();
}
};
for (int i = 0; i < 3; i++) {
void (^subblock)(void) = ^{
NSLog(#"%s: in subblock %d", __PRETTY_FUNCTION__, i);
};
[subblocks addObject:subblock];
}
blockWithBlocks();
}
return 0;
}
Note that the requirements for copying blocks under ARC have been in flux. Previously it would have been necessary to write [subblocks addObject:[subblock copy]]; rather than simply [subblocks addObject:subblock]; Under the current semantics described in the clang documentation
With the exception of retains done as part of initializing a __strong parameter variable or reading a __weak variable, whenever these semantics call for retaining a value of block-pointer type, it has the effect of a Block_copy. The optimizer may remove such copies when it sees that the result is used only as an argument to a call.
the only times that it is necessary to copy a block to be sure that it is no longer on the stack is when the block is being passed as an argument to a function/method that has a __strong parameter variable and when the block is being read from a __weak variable.
What do you mean "add code dynamically to a block"? How is that different from simply making a new block from the "code" and the original block?
If the difference is that you want to have a reference to a block and have its behavior change without having to assign a new block to that reference, then you can have the block capture mutable state, where the mutable state could contain the block(s) to call, which you can then change, like what #NateChandler suggests.
If the difference is that is that you can choose between several different pieces of "code", so you cannot hard-code it at the place you are creating the block, then you can just make the "pieces of code" into blocks and select the right block to put into the new block.

ARC __block behavior equivalent in MRC?

As you know, in ARC, __block variables of object pointer type used in a block are retained by the block. So take the following simplified example:
__block id foo = getObject();
void (^aBlock)() = ^ {
NSLog(#"%#", foo);
foo = getObject();
}
runBlockAsynchronouslyMultipleTimes(aBlock);
The object pointed to by foo is retained by the block, so that when the block is run (asynchronously), the object is still valid and can be printed. When we do the assignment within the block, ARC manages it like any other strong reference (the old value is released and the new value retained). (The assignment forces us to use __block in the first place.) And when the block is not needed anymore, ARC somehow releases its retained object pointed to by foo at that point (it is not leaked).
Okay, now suppose I want to do the same thing under MRC (why is not important; this is an question about the language). As you know, __block variables of object pointer type used in a block are NOT retained by the block in MRC. Which is fine; we'll manage it ourselves (this is MRC, after all). So the attempt looks like this:
__block id foo = [getObject() retain];
void (^aBlock)() = ^ {
NSLog(#"%#", foo);
[foo release];
foo = [getObject() retain];
}
runBlockAsynchronouslyMultipleTimes(aBlock);
// where to release foo?
Most of it is straight-forward -- the object is retained by us initially manually; inside the block, when we re-assign the pointer, we release and retain the new value as appropriate.
But then comes the problem: How do we release the object when the block is not needed anymore? Since we manually manage the memory, we should ideally manually release the object when the block is deallocated. But there doesn't seem to be an easy way to do so.
I could think of maybe one way: using associative references to tie the object to the block. But then to re-assign the associative reference inside the block, the block would need a reference to itself, so the block variable would also need to be __block and the block needs to be copied prior to setting the variable. Which is all very ugly. Or, we put the object inside a mutable container object that is then retained by the block; but that is ugly too.
The mutable container is about as clean as you can get. You could create a simple wrapper with a single object property to clean it up a little, and then you would get memory management from the property accessors.
An approach which would look cleaner, but is actually kind of messy underneath, would be to have an immutable wrapper which took a pointer, and just released that pointer when it was deallocated.
#interface ObjectReleaser : NSObject {
id *objectPointer;
}
- (id)setObjectPointer:(id *)pointer;
- (void)captureMe;
#end
#implementation ObjectReleaser
- (void)setObjectPointer:(id *)pointer {
if(!objectPointer && pointer) {
objectPointer = pointer;
[*objectPointer retain];
}
}
- (void)dealloc {
if(objectPointer) [*objectPointer release];
[super dealloc];
}
- (void)captureMe {} // Blocks can call this to capture the object
#end
The block would catch and retain this object, since it is not __block. You would modify your __block object as usual, with all of the proper retains and releases. Then, when the block is deallocated, it will release the releaser, which will then be deallocated and release whatever your pointer currently points to.
__block id foo = getObject();
ObjectReleaser *releaser = [[ObjectReleaser alloc] init];
void (^aBlock)() = ^ {
[releaser captureMe];
NSLog(#"%#", foo);
[foo release];
foo = [getObject() retain];
}
aBlock = [aBlock copy];
[releaser setObjectPointer:&foo];
Note that you don't need to retain foo just for the block, because the releaser does that for you. You do have to set the releaser's pointer after copying the block, since the copy will change foo's pointer. This is also why it is safe to save the pointer of a stack variable after your function returns: the variable is not actually on the stack.

How can code inside an Objective-C block reference the block object itself?

self is merely a captured variable inside a block and doesn't reference the block itself, so how does a block reference itself without having an explicit captured variable for that purpose?
__block void(^strawberryFields)();
strawberryFields = [^{ strawberryFields(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
strawberryFields);
you use the __block because the block will make a copy of the value of strawberryFields when the block is created which will be before the assignment.
you also must copy the block prior to any other copy operation or else you'll end up with a block that references the on-stack original version.
note that the above code leaks the block. Somewhere, there needs to be a release of that block to balance the copy.
I found this pattern to work and stable for ARC (automatic reference counting), both in Debug and Release builds.
-(void) someMethod
{
// declare a __block variable to use inside the block itself for its recursive phase.
void __block (^myBlock_recurse)();
// define the block
void (^myBlock)() = ^{
// ... do stuff ...
myBlock_recurse(); // looks like calling another block, but not really.
};
// kickstart the block
myBlock_recurse = myBlock; // initialize the alias
myBlock(); // starts the block
}
Initially I tried just putting a __block modifier to myBlock and use that variable directly to recurse within the block's implementation. That works on the ARC Debug build but breaks with an EXC_BAD_ACCESS on the Release build. On the other hand removing the __block modifier raises a "variable not defined when captured by block" warning (and I was reluctant to run it and test).
I have never tried this before and not 100% sure it's useful, if valid, but for example:
typedef void (^BasicBlock)(void);
__block BasicBlock testBlock;
testBlock = ^{NSLog(#"Testing %p", &testBlock);};
testBlock();
You probably have declare the variable with __block to prevent self-retain cycle.
The block needs some way to nil out its own reference. Typically it is done by storing the block in a property of the class.
Sometimes you can prefer to not use a property. Here is how you do it without a property:
__weak id weakSelf = self;
__block id block = ^{
if(weakSelf) {
// .. do whatever
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
else {
block = nil;
}
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
The key thing to keep in mind is that all code paths must lead to a block = nil. We do that here by calling the block every 5 seconds until weakSelf turns nil.
Note that in ARC, it's a little different -- __block object pointer variables are by default retained in ARC, unlike in MRC. Thus, it will cause a retain cycle. It is necessary for the block to capture a weak reference to itself (using __weak) in order to not have a retain cycle.
However, we still need a strong reference to the block somewhere. If there are no strong references, the block (which is on the heap since it's copied) will be deallocated. Thus, we need two variables, one strong and one weak, and inside the block use the weak one to reference itself:
__block __weak void(^weakBlock)();
void(^myBlock)();
weakBlock = myBlock = [^{ weakBlock(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
myBlock);