Posts Tagged ‘Blocks’

Objective-C Blocks as Tuples Replacement

Thursday, August 14th, 2014

When programming you sometimes want to return multiple values from a function. The problem is that many languages only support one return value per function. A commonly used solution is to pass values by reference as input parameters to the function and “misuse” these as output parameters. Some languages (or libraries) – e. g. Swift – provide a tuple type where you can pack multiple values together so you can return multiple values as a tuple. You can also put your return values in some other kind of container, e. g. a dictionary or an array. All these solutions have their pitfalls, mostly some kind of loosing the type of the return values or having to box and unbox primitive values or just being cumbersome or hard to read.

Recently I came up with another idea how to get multiple return values from a function: If the used language supports some sort of closures (e. g. blocks in Obj-C) simply let the caller pass a closure that receives the return values with their proper types and call that closure to return the values.

An example in Objective-C:
Let’s create a class extension to NSArray that assumes the array just contains NSString objects and searches for the string that appears most often in that array. The result values are the number of occurrences of the string and the string itself.

@interface NSArray (MyExtension)
- (void)findMostUsedString:(void (^)(int count, NSString *string))result;
@end

@implementation NSArray (MyExtension)

- (void)findMostUsedString:(void (^)(int count, NSString *string))result
{
	// do the heavy calculation:
	int maxCount = 0;
	NSString *maxString = nil;
	@autoreleasepool {
		NSMutableDictionary *counters = [NSMutableDictionary dictionary];
		for(NSString *string in self) {
			@autoreleasepool {
				int count = [counters[string] intValue] + 1;
				counters[string] = @(count);
				if (count > maxCount) {
					maxCount = count;
					maxString = string;
				}
			}
		}
	}

	// return the result consisting of multiple values
	// by calling the passed block:
	result(maxCount, maxString);
}

@end

Now you can use that function returning two values as simple as that:

NSArray *array = @[@"foo", @"bar", @"foo", @"foobar", @"42", @"foo"];
[array findMostUsedString:^(int count, NSString *string) {
	NSLog(@"Found \"%@\" %d times", string, count);
}];

Output is:

Found "foo" 3 times

Blocks not capturing “by reference” variables

Monday, May 21st, 2012

I recently stumbled over a strange case when using blocks.

Please look at the following bit of  Objective-C++ code:

typedef void (^BlockType)();

static BlockType blockTestByValue(const int value)
{
	return [[^{NSLog(@"blockTestByValue &value = %p", &value);} copy] autorelease];
}

static BlockType blockTestByReference(const int& value)
{
	return [[^{NSLog(@"blockTestByReference &value = %p", &value);} copy] autorelease];
}

void test()
{
	BlockType direct;
	BlockType byValue;
	BlockType byReference;
	{
		int value = 42;
		NSLog(@"&value = %p", &value);
		direct = [[^{NSLog(@"direct &value = %p", &value);} copy] autorelease];
		byValue = blockTestByValue(value);
		byReference = blockTestByReference(value);
	}
	direct();
	byValue();
	byReference();
}

Calling test() gives the following output:

&value = 0x7fff5fbff44c
direct &value = 0x100c26a10
blockTestByValue &value = 0x100c26990
blockTestByReference &value = 0x7fff5fbff44c

You see, we have a stack based variable value here that is used by blocks that are executed outside the living context of the variable value. Therefore the value variable gets “captured” by the block and a copy is made. This is true for all cases – except for the case where I pass the value variable by reference to a function! I don’t see any reason why the variable should not be captured in this case. In my opinion the blockTestByReference case should behave exactly like the direct case, because in both cases value is referencing exacly the same variable.

Any comments? Did I miss something in the specification of blocks, or did a discover a bug in the compiler?

Update:

I found the behavior described in the language specification:

For example, given class Foo with member function fighter(void):
      Foo foo;
      Foo &fooRef = foo;
      Foo *fooPtr = &foo;

...a Block that used foo would import the variables as const variations:
       const Foo block_foo = foo;	// const copy constructor
       const Foo &block_fooRef = fooRef;
       Foo *const block_fooPtr = fooPtr;

So the compiler is really correct here. One must be very careful when using variables declared by reference in blocks!

Grand TableView Dispatch

Friday, August 19th, 2011

Just a little programming trick that might be interesting for other programmers:

I am working on a project where I have a (view based) NSTableView that should display a value in each row. These values are calculated from other values that are fetched from a database. While the performance of getting one single value is acceptably fast (under 0.1 seconds) for other use cases of the application, this sums up in the table view and noticably blocks the user interface whenever the table needs to be reloaded or when scrolling through the table.

My first idea was to calculate the values in a separate thread and then update the GUI whenever a value is available. Problem here is that the model is not thread-safe at this point and that would be a ton of work to change.

So I decided that the values for the table should be calculated on the main thread as before, but the main runloop should get a chance to do its work between every calculation of a single value to keep the user interface as responsive as possible. A great situation for Grand Central Dispatch and the use of Blocks! So I wrote something like that for every requested value in the table view:

dispatch_async(dispatch_get_main_queue(), ^{
+++// calculate value and update the GUI
});

… unfortunately, that did not work as expected. The GUI still blocked until all values for all requested rows of the tableview where calculated. It seems the blocks were correctly added to the main queue, but as soon as the process returned to the runloop, the whole queue was processed in one pass without checking for events in between the individual enqueued blocks. So the behaviour did not change in any way. After some thinking I came up with the following interesting solution:

dispatch_async(mySerialQueue, ^{
+++dispatch_sync(dispatch_get_main_queue(), ^{
++++++// calculate value and update the GUI
+++});
});

So for every requested table row I add a new block to a queue that runs on a separate thread and processes its blocks in serial order. These blocks, processed on a separate thread, do just one thing: they add another block to the main queue and wait until this block is processed (dispatch_sync) before adding the next block. Finally these blocks, processed on the main thread, calculate the row values and update the GUI like before. Because of this transitions from the separate thread to the main thread, the main runloop gets a chance to process other events between every value calculation.

I find it interesting how much complicated work can be expressed in so few lines of code. Writing all this functionality “by hand” without using Grand Central Dispatch and Blocks would make it very complicated and probably less efficient.