Oct 29 2012

Tiny Programs, the Atomic Edition

Readers of this blog might notice a pattern in my postings. They’re occasionally accompanied by a small program to demonstrate some interesting point.

Much of the sample code in Advanced Mac OS X Programming : The Big Nerd Ranch Guide are in a similar form: a small stand-alone program that demonstrates some isolated bit of functionality.

I love small little programs. They’re not just a pedagogical tool (even though they’re great for that). I find them invaluable when I need an answer to a question about how something works, or if I’m tracking down some kind of misbehavior whether from a bug or just my own misunderstanding.

I have a directory, ~/junk, where I put these little one offs. You can tell I’ve collected a couple (and I clean out the junk pile every now and then!)

Small program listing

Ever been involved in a discussion, either in person, or online line via email or IRC? One of those speculation threads on how something works. Person A thinks it works one way. Person B remembers hearing something from someone about how it works a different way. Person C used it years ago and remembered it working the first way. Around and around it goes. Sometimes some interesting ideas are tossed around, but often it can be a waste of time. I tend to be the party pooper by taking a minute or three and trying it in a test program.

It’s like the Scientific Process. You have a hypothesis. You write an experiment to test that hypothesis. You get some data based on that outcome, and then feed that data back into your personal pile of understanding.

One little piece of performance art I do in my classes and when I give my “Thoughts on Debugging” talk is to demonstrate writing and running one of these little programs in a couple of minutes – complete with typos. Many editors include built-in shell access which makes doing a quick command-line compile very easy. There are also standalone snippet tools that will let you run chunks of Objective-C (or many other languages) without the hassle of making a brand new Xcode project for each one.

An Application

Just the other day, we had a style discussion about where nonatomic should live in a property declaration. At the beginning, where it’s been historically:

@property (nonatomic, assign) NSInteger frobnozzle;

or at the end

@property (assign, nonatomic) NSInteger frobnozzle;

As far as the compiler is concerned, they’re the same. The argument for having nonatomic at the end was that you could use the macro NS_NONATOMIC_IOSONLY for shared code:

@property (assign, NS_NONATOMIC_IOSONLY) NSInteger frobnozzle;

That macro evaluates to nonatomic on iOS, and to nothing on Mac OS X. This macro has to be the last one in the list, because the compiler will happily eat a comma at the end of the list:

@property (assign, ) NSInteger frobnozzle;

But not at the beginning:

@property (, assign) NSInteger frobnozzle;

Giving an error:

atomic.m:8:12: error: expected ')'
@property (, assign) NSInteger commaAtBeginning;
           ^
atomic.m:8:11: note: to match this '('
@property (, assign) NSInteger commaAtBeginning;

So, by putting nonatomic at the end it becomes easier to migrate some iOS code to be shared with its desktop counterparts as well. Just replace atomic with NS_NONATOMIC_IOSONLY, and you’re done with that part.

Easy enough to test that leading/trailing comma hypothesis with a little program (the final version can be found at this gist):

#import <Foundation/Foundation.h>

// clang -g -Wall -framework Foundation -o atomic atomic.m

@interface Blah : NSObject
@property (assign, NS_NONATOMIC_IOSONLY) NSInteger frobnozzle;
@property (assign, ) NSInteger commaAtEnd;
@property (, assign) NSInteger commaAtBeginning;  // Syntax error
@end // Blah

@implementation Blah
@end // Blah

int main (void) {
    return 0;
} // main

I only had to compile it and see what happens. No need to actually run anything. Sure enough, comma at the beginning of the list is rejected, and a comma at the end of the list is allowed. The question that came up next was “why does NS_NONATOMIC_IOSONLY evaluate to nothing, and not atomic“. The thought was atomic doesn’t exist because it’s the default. A quick tweak to the test program showed that atomic actually does exist:

@property (atomic, assign) NSInteger blah;

This compiled ok. Just to make sure that this atomic actually means “Objective-C property access atomic”, I added a getter but not a setter. The compiler warns in the case where one part of the property access is compiler-generated, and the other part is implemented in the source file. This makes sense because we can’t correctly assume how the compiler will be making the property atomic. If the setter is using one technique and our code is using another, it’s no longer an atomic property.

(Just a reminder that atomic properties don’t mean it’s thread safe, just that assigning and reading the value of the instance variable will occur in its entirety. If you have explicit thread safety requirements, you’ll need to use something like the atomic test and set calls, locks, queues, and so on.)

So, I added a getter:

- (NSInteger) blah {
    return _blah;
} // blah

And sure enough, the compiler warns:

atomic.m:16:1: warning: writable atomic property 'blah' cannot pair a synthesized setter with a user
      defined getter [-Watomic-property-with-user-defined-accessor]
- (NSInteger) blah {
^
atomic.m:16:1: note: setter and getter must both be synthesized, or both be user defined,or the property
      must be nonatomic
atomic.m:9:38: note: property declared here
@property (atomic, assign) NSInteger blah;
                                     ^

This is interesting data. Clang has support for explicit atomic properties. Yet that NS_NONATOMIC_IOSONLY macro evaluates to nothing. Looking at the compiler source code, ParseObjc.cpp has code for finding atomic properties:

    else if (II->isStr("nonatomic"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
    else if (II->isStr("atomic"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic);

But Apple’s documentation only mentions nonatomic, and in fact says that “There is no keyword to denote atomic.”

Now I’m curious. Maybe there’s another reason. Nowadays with clang being so good, I forget about gcc. Maybe gcc has problems with the atomic keyword. Let’s check.

I added a new compiler line to the top:

// gcc -g -Wall -framework Foundation -o atomic atomic.m

Copy and paste it into a shell and build it:

% gcc -g -Wall -framework Foundation -o atomic atomic.m
atomic.m:9: error: expected a property attribute before ‘atomic'

Yep. gcc doesn’t like that. A quick browse of the gcc source shows that nonatomic is the only keyword in c-parser.c:

...
  { "retain",           RID_RETAIN,             D_OBJC },
  { "copy",             RID_COPY,               D_OBJC },
  /* APPLE LOCAL end objc new property                 */
  /* APPLE LOCAL radar 4947014 - objc atomic property */
  { "nonatomic",        RID_NONATOMIC,          D_OBJC },
};

So, indeed in gcc, there is no atomic property for Objective-C. Not all the mysteries are solved (is atomic really OK to use if we’re not going to be using gcc?), but it does explain why NS_NONATOMIC_IOSONLY is the way it is, because it needs to be compatible with gcc.

Interested in debugging, command-line tools, the compiler, and similar low-level nerdity? Come to my Advanced Mac OS X Bootcamp, January in the Netherlands, and February in Atlanta. Or stop by and say “Hi” to the Ranchers at CocoaConf Raleigh in November.

3 Comments

  1. Thomas Ferraro

    Can you recommend tool for running C or Objective-C snippets?

Leave a Comment

Join the discussion. Do not worry, your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>