The Elegant Chaos Blog
News, thoughts, and other ramblings from the world of Elegant Chaos.

In my Mac Pro Update - Think Different post a few weeks ago, I said that I thought we don’t really need a great big new Mac Pro from Apple.

What we need instead (and I admit that I don’t have an exact technical solution for this problem, but nevertheless) is a unit or units that can seemlessly enhance the processing power of a laptop when it’s on our home network.

You could argue that there’s still a need for a big box that can host all sorts of large expansion cards, but I’m not really convinced. Thunderbolt should deal with most of that.

Something else has occurred to me recently.

People have been talking about a potential switch away from Intel to ARM for the Mac range, and assuming that it would happen first with a Mac Mini or an iMac, since they are seen as “consumer”, and there’s a perception that consumer machines will be easier to switch over.

I actually think that the opposite will happen. I think that the first ARM Mac is likely to come in the guise of a new “Pro” desktop box. I also think that it’s likely to be loaded to the gills with cores, to the extent that it blows away anything out there in terms of raw processing power.

With GCD / blocks / NSOperation, Cocoa has a really nice clean model for making use of multiple cores. Better than anything I’ve used before (although admittedly I’m now a bit out of date with regard to the competition).

With the expansion of privelege separation and things like XPC, we’re also moving closer to a world where even a single app could be run seamlessly across multiple machines.

It seems to me that switching to a relatively low power, low cost, risc architecture makes perfect sense in this world.

Before you ask - I’ve absolutely no evidence for this. Just thinking aloud…

Read more...

October 05, 2012

Simon Wolf wrote a blog post recently talking about passing NSError pointers into methods like this:

NSError* error = nil;
[something someMethod:@"blah" error:&error];

He talked about the fact that when you do this, you should always check the result of the method before using the error. In other words, you do this:

NSError* error = nil;
if (![something someMethod:@"blah" error:&error])
{
	NSLog(@"got error %@", error);
}

and not this:

NSError* error = nil;
[something someMethod:@"blah" error:&error];
if (error)
{
	NSLog(@"got error %@", error);
}

This is good advice. The method you’re calling isn’t guaranteed to set error to a non-nil value if nothing goes wrong. It might leave it alone, but it might set it to a temporary value, even though it eventually returns an “ok” result.

However, Simon then went on to talk about this line at the top:

NSError* error = nil;

His assertion was that by setting error to nil, you’re indicating that you intend to test it after the call - in other words that it’s an indicator that you don’t know what you’re doing.

He suggested that you should just do this:

NSError* error;

Strictly speaking, this is correct. If the method you’re calling follows the implicit contract for such functions, this should be fine.

However, I always set the error to nil before I pass it in, even though I never test it after the call. Why do I do this?

Consider the following method:

- (BOOL)someMethod:(NSString*)string error:(NSError**)error
{
	if (error)
	{
		if (something)
			*error = [self doSomeStuff];
		else (somethingelse)
			*error = [self doSomethingElse];
		//... lots of other cases here...
		
		//... later
		
		if ([(*error) code] == someCode)
		{
			[self doSomeExtraStuff];
		}
	}
	
	return YES;
}

This is a bit of a contrived example, but the point is that this method might be the one you’re calling, and it might be in a third party library that you have no control over.

Now lets imagine that some refactoring or other code change introduces a bug where *error doesn’t get set in the first block of if/else statements. Let’s also imagine that the developer has the relevant warnings turned off, and doesn’t noticed (shock horror - some people actually do this!).

What happens when the code starts accesses *error? Well, it depends what’s in it. If you did this:

NSError* error = nil;

you’ll be fine.

If you did this:

NSError* error;

you get undefined behaviour, based on what happened to be on the stack in the position that the error variable occupies. It’s a classic uninitialised variable bug, and potentially a bastard to track down.

At this point you may well be saying “if the quality of the library you’re using is that bad, you’ve only yourself to blame”. You might have a point, but bugs do creep in, even to good libraries.

Admittedly too, when you’re accessing an uninitialised Objective-C pointer, you’re way more likely to crash straight away than you would have been if you were just dereferencing a pointer to read a member in C/C++.

However, all of this is the reason why I still do:

NSError* error = nil;

even though I’m not going to test error afterwards.

You could call it paranoia, but don’t mistake it for misunderstanding the NSError** contract!

Read more...

So, yesterday’s 1.1.2b5 release didn’t quite go according to plan, as it contained a rather serious bug which corrupted it’s store of cached information. The result of this was that when you relaunched it, Ambientweet encountered problems and generally ended up in a non functional state.

Luckily, I can now bring you 1.1.2b6, now with added not-so-many-bugs-honest.

Since it’s only been a day and people may not have read the previous post, it’s worth re-iterating the changes in these new versions, so here’s an edited version of yesterday’s message:

I’ve been working on some improvements to Ambientweet, for the next version, which I’m currently calling 1.1.2 (although it’s getting to the point where there are enough changes to warrant calling it 1.2).

Internally, the code that manages the communication with Twitter has been modified a fair bit. This was partly a case of tidying up some old code, and partly improving the design to make it easier to support multiple Twitter accounts at once.

I’ve not quite got as far as multiple Twitter accounts in this revision, but I have added support for multiple windows. This means that you can set up more than one Ambientweet window if you wish, and have them track different timelines. One could track your normal timeline, one could focus on tweets from a single user, and one could show the results of a search for some text or a hashtag.

Because you can now have different windows, I’ve removed the window related settings from the preferences, and instead added a “Window Options” menu to the “View” menu, so that you can set them individually for each window.

The other major change that has happened relates to the automatic update mechanism. Unfortunately this got broken in version 1.1.1, and as a result automatic updating may not work, particularly if you are running Mountain Lion. These problems should now be fixed, but if you’re running one of the versions where updating was broken, then unfortunately you’ll have to manually get yourself past this version by downloading the latest beta.

Other than that, there are a couple of minor fixes:

  • The preview display which says what tweets are being downloaded (before there are any to display) should now make a bit more sense, and shouldn’t show an ugly looking internal description for a user any more.
  • The preference for centring the window when it shows some sort of sheet (eg when you’re asked to enter the text to search for) now actually does something.

If you are feeling brave, you can download the latest version here.

Read more...

August 27, 2012

I’ve been working on some improvements to Ambientweet, for the next version, which I’m currently calling 1.1.2 (although it’s getting to the point where there are enough changes to warrant calling it 1.2).

Internally, the code that manages the communication with Twitter has been modified a fair bit. This was partly a case of tidying up some old code, and partly improving the design to make it easier to support multiple Twitter accounts at once.

I’ve not quite got as far as multiple Twitter accounts in this revision, but I have added support for multiple windows. This means that you can set up more than one Ambientweet window if you wish, and have them track different timelines. One could track your normal timeline, one could focus on tweets from a single user, and one could show the results of a search for some text or a hashtag.

Because you can now have different windows, I’ve removed the window related settings from the preferences, and instead added a “Window Options” menu to the “View” menu, so that you can set them individually for each window.

The other major change that has happened relates to the automatic update mechanism. Unfortunately this got broken in version 1.1.1, and as a result automatic updating may not work, particularly if you are running Mountain Lion. These problems should now be fixed, but if you’re running one of the versions where updating was broken, then unfortunately you’ll have to manually get yourself past this version by downloading the latest beta.

Other than that, there are a couple of minor fixes:

  • The preview display which says what tweets are being downloaded (before there are any to display) should now make a bit more sense, and shouldn’t show an ugly looking internal description for a user any more.
  • The preference for centring the window when it shows some sort of sheet (eg when you’re asked to enter the text to search for) now actually does something.

If you are feeling brave, you can download the latest version here.

Read more...

If you work with submodules in git, and you’ve ever tried to move a repository locally to a different place on your machine, you may have encountered a problem.

In recent versions of git, the embedded submodules don’t have their own “.git” directory. Instead they contain a text file called .git which points git back at the root .git directory, which contains all the information for all submodules. Furthermore, there’s a config file for each submodule, hidden in the main .git directory, which points “forward” to the submodule.

That would all be fine except for one incredibly stupid thing: in versions of git prior to 1.7.10, this path was stored in absolute format.

Which means that if you move the repo on your disk, all of these paths break, and the repo no longer works!

This is, to put it mildly, a bit of a pain in the arse.

What to do?

The long answer is to go through all of the submodules and do the following:

  • hand edit the gitdir: entry in the .git file to make it relative
  • hand edit the config file in the directory that the gitdir entry points to, to make the worktree entry relative

That’s all fine and dandy, but it’s a tricky process, and if you’ve got lots of submodules, some of which may even have embedded submodules, it’s a lot of work.

Luckily, there’s a short answer:

  • do a search and replace across the .git and config files mentioned above, and replace the old broken absolute path with a new correct absolute path.

This isn’t ideal, but it gets you working again.

What’s more, it’s a lot easier to automate. Figuring out the proper relative paths isn’t that easy to automate, but doing a search and replace of one known string with another across a bunch of files is.

Here’s a script I wrote to do it.

It’s not a perfect script, and please be aware that it makes permanent changes to files so you may well want to zip up the whole of your repo first as a paranoid backup.

However, it seems to work for me. It could take the old and new paths as parameters, but I decided to embed them in the script for a couple of reasons.

One, it’s a better example of what the paths should look like. Two, this situation is most likely to occur when you’ve made some sort of global change, like renaming or changing your hard drive. In that case you’ll probably want to do the same replacement lots of times on different repos, so embedded it in the script is helpful (and also reduces the risk of typing it wrong).

Read more...