Using #synchronized(self) { ... } in class-function - objective-c

Accidentally I have been using a #synchronized block with the semaphore self in a class method.
+(void)someFunction {
#synchronized(self) {
/* some code */
}
}
It seems to be valid code, at least the compiler does not give me any bad feedback. My question is: what is self here? As far as I can tell the #synchronized block didn't work, but it didn't crash either.
I'm just asking out of curiousity.

self in this instance refers to the class, instead of an instance. In ObjC, classes are themselves objects.

self in this context is the class itself, it's perfectly fine to use #synchronized in a class function since they are also Objective-C objects.

The #synchronized syntax is a compiler extension for mutex implementation. I assume you understood what it does. The compiler will translate it into something else, supposedly something similar to critical section because it's less CPU intensive. Locks need to be tracked. The implementation will use an object to record the state of the lock, to keep its integrity (i.e. a lock shouldn't be acquired twice, or unlocked twice).
In #synchronized(self), the object doesn't have to be self. It could be any objective-c object. Note that a single #synchronized block usually does nothing (when you mentioned it's not working, it's actually behaving correctly). But when you have two #synchronized blocks on the same object, only one block will be executed at the same time, the other block would have to wait for the lock to be unlocked (i.e. the first block finishes). This helps to keep things synchronized as in a multithreaded environment.

In a class method self is the class that the method is being called on. For example you can call other class methods of the same class using self. [MyClass someFunction] and [self someFunction] would be the equivalent to recursively calling someFunction. The #synchronized block I am sure worked as it was supposed to.

Related

Objective-C: How to force a call to `+initialize` at startup rather than later when the class happens to used for the first time?

Problem
For certain classes, I would like to explicitly call the +initialize method when my program starts, rather than allowing the runtime system to call it implicitly at some nondeterministic point later when the class happens to first be used. Problem is, this isn't recommended.
Most of my classes have little to no work to do in initialization, so I can just let the runtime system do its thing for those, but at least one of my classes requires as much as 1 second to initialize on older devices, and I don't want things to stutter later when the program is up and running. (A good example of this would be sound effects — I don't want sudden delay the first time I try to play a sound.)
What are some ways to do this initialization at startup-time?
Attempted solutions
What I've done in the past is call the +initialize method manually from main.c, and made sure that every +initialize method has a bool initialized variable wrapped in a #synchronized block to prevent accidental double-initialization. But now Xcode is warning me that +initialize would be called twice. No surprise there, but I don't like ignoring warnings, so I'd rather fix the problem.
My next attempt (earlier today) was to define a +preinitialize function that I call directly instead +initialize, and to make sure I call +preinitialize implicitly inside of +initialize in case it is not called explicitly at startup. But the problem here is that something inside +preinitialize is causing +initialize to be called implicitly by the runtime system, which leads me to think that this is a very unwise approach.
So let's say I wanted to keep the actual initialization code inside +initialize (where it's really intended to be) and just write a tiny dummy method called +preinitialize that forces +initialize to be called implicitly by the runtime system somehow? Is there a standard approach to this? In a unit test, I wrote...
+ (void) preinitialize
{
id dummy = [self alloc];
NSLog(#"Preinitialized: %i", !!dummy);
}
...but in the debugger, I did not observe +initialize being called prior to +alloc, indicating that +initialize was not called implicitly by the runtime system inside of +preinitialize.
Edit
I found a really simple solution, and posted it as an answer.
The first possible place to run class-specific code is +load, which happens when the class is added to the ObjC runtime. It's still not completely deterministic which classes' +load implementations will be called in what order, but there are some rules. From the docs:
The order of initialization is as follows:
All initializers in any framework you link to.
All +load methods in your image.
All C++ static initializers and C/C++ __attribute__(constructor)
functions in your image.
All initializers in frameworks that link to you.
In addition:
A class’s +load method is called after all of its superclasses’ +load
methods.
A category +load method is called after the class’s own +load method.
So, two peer classes (say, both direct NSObject subclasses) will both +load in step 2 above, but there's no guarantee which order the two of them will be relative to each other.
Because of that, and because metaclass objects in ObjC are generally not great places to set and maintain state, you might want something else...
A better solution?
For example, your "global" state can be kept in the (single) instance of a singleton class. Clients can call [MySingletonClass sharedSingleton] to get that instance and not care about whether it's getting its initial setup done at that time or earlier. And if a client needs to make sure it happens earlier (and in a deterministic order relative to other things), they can call that method at a time of their choosing — such as in main before kicking off the NSApplication/UIApplication run loop.
Alternatives
If you don't want this costly initialization work to happen at app startup, and you don't want it to happen when the class is being put to use, you have a few other options, too.
Keep the code in +initialize, and contrive to make sure the class gets messaged before its first "real" use. Perhaps you can kick off a background thread to create and initialize a dummy instance of that class from application:didFinishLaunching:, for example.
Put that code someplace else — in the class object or in a singleton, but in a method of your own creation regardless — and call it directly at a time late enough for setup to avoid slowing down app launch but soon enough for it to be done before your class' "real" work is needed.
There are two problems here. First, you should never call +initialize directly. Second, if you have some piece of initialization that can take over a second, you generally shouldn't run it on the main queue because that would hang the whole program.
Put your initialization logic into a separate method so you can call it when you expect to. Optionally, put the logic into a dispatch_once block so that it's safe to call it multiple times. Consider the following example.
#interface Foo: NSObject
+ (void)setup;
#end
#implementation Foo
+ (void)setup {
NSLog(#"Setup start");
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(#"Setup running");
[NSThread sleepForTimeInterval:1]; // Expensive op
});
}
#end
Now in your application:didFinishLaunchingWithOptions: call it in the background.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"START");
// Here, you should setup your UI into an "inactive" state, since we can't do things until
// we're done initializing.
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0, 0), ^{
[Foo setup];
// And any other things that need to intialize in order.
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(#"We're all ready to go now! Turn on the the UI. Set the variables. Do the thing.");
});
return YES;
}
This is how you want to approach things if order matters to you. All the runtime options (+initialize and +load) make no promises on order, so don't rely on them for work that needs that. You'll just make everything much more complicated than it needs to be.
You may want to be able to check for programming errors in which you accidentally call Foo methods before initialization is done. That's best done, IMO, with assertions. For example, create an +isInitialized method that checks whatever +setup does (or create a class variable to track it). Then you can do this:
#if !defined(NS_BLOCK_ASSERTIONS)
#define FooAssertInitialized(condition) NSAssert([Foo isInitialized], #"You must call +setup before using Foo.")
#else
#define FooAssertInitialized(condition)
#endif
- (void)someMethodThatRequiresInitialization {
FooAssertInitialized();
// Do stuff
}
This makes it easy to mark methods that really do require initialization before use vs ones that may not.
Cocoa provides a setup point earlier than +initialize in the form of +load, which is called very shortly after the program's start. This is a weird environment: other classes that rely on +load may not be completely initialized yet, and more importantly, your main() has not been called! That means there's no autorelease pool in place.
After load but before initialize, functions marked with __attribute__((constructor)) will be called. This doesn't allow you to do much that you can't do in main() so far as I know.
One option would be to create a dummy instance of your class in either main() or a constructor, guaranteeing that initialize will be called as early as possible.
Answering my own question here. It turns out that the solution is embarrassingly simple.
I had been operating under the mistaken belief that +initialize would not be called until the first instance method in a class is invoked. This is not so. It is called before the first instance method or class method is invoked (other than +load, of course).
So the solution is simply to cause +initialize to be invoked implicitly. There are multiple ways to do this. Two are discussed below.
Option 1 (simple and direct, but unclear)
In startup code, simply call some method (e.g., +class) of the class you want to initialize at startup, and discard the return value:
(void)[MyClass class];
This is guaranteed by the Objective-C runtime system to call [MyClass initialize] implicitly if it has not yet been called.
Option 2 (less direct, but clearer)
Create a +preinitialize method with an empty body:
+ (void) preinitialize
{
// Simply by calling this function at startup, an implicit call to
// +initialize is generated.
}
Calling this function at startup implicitly invokes +initialize:
[MyClass preinitialize]; // Implicitly invokes +initialize.
This +preinitialize method serves no purpose other than to document the intention. Thus, it plays well with +initialize and +deinitialize and is fairly self-evident in the calling code. I write a +deinitialize method for every class I write that has an +initialize method. +deinitialize is called from the shutdown code; +initialize is called implicitly via +preinitialize in the startup code. Super simple. Sometimes I also write a +reinitialize method, but the need for this is rare.
I am now using this approach for all my class initializers. Instead of calling [MyClass initialize] in the start up code, I am now calling [MyClass preinitialize]. It's working great, and the call stack shown in the debugger confirms that +initialize is being called exactly at the intended time and fully deterministically.

Destroying self from within self

I have an Objective-C class whose instances can detect when they are no longer needed and destroy themselves, but I am looking for a safe way to trigger an object's self-destruction from within the object itself, without somehow "destroying the method that is calling the destruction"... My code looks roughly like this (some removed for brevity):
+ (oneway void)destroyInstance:(id)obj {
printf("Destroying.\n");
if (obj != nil) {
free(obj);
obj = nil;
}
}
- (oneway void)release {
_noLongerRequired = [self determineIfNeeded]; // BOOL retVal
if (_noLongerRequired) {
[self deallocateMemory]; // Free ivars etc (NOT oneway)
[MyClass destroyInstance:self]; // Oneway
}
}
If I call -release, it should return instantly to the main thread (due to the oneway).
Meanwhile, if the instance finds it is no longer needed, it should then call the oneway class method destroyInstance: and remove itself from the runtime. My question is, is this safe?? And have I used oneway correctly? It seems to me there is the possibility of destroying the instance's -release function before it returns, which could be... rather bad..?
(PS: Obviously not looking for anything to do with NSObject, etc :))
This is without a doubt a terrible idea if you want working and maintainable software and unsafe in just about any context. But sometimes terrible, unsafe ideas can be fun on the weekend, so I'll answer the components of the question I can discern.
A method will not get "destroyed" because an instance is deallocated. What can happen is that self can end up pointing to deallocated memory during the execution of a method, which means that accessing self or any instance variables during this time can crash.
As to the rest of your code, there is no reason at all to set obj equal to nil in +destroyInstance, so if you were trying accomplish something in particular (nil'ing out pointers to the object perhaps) that way is not the right way to go about it.
Thinking about the use of oneway, what the language says is that sending this message won't block the calling thread. In the context of releasing objects I think it makes some sense, as presumably the target of the message won't ever be referenced by that thread again. By that logic I'd think your declaration of +destroyInstance is maybe OK. I do wonder if you'd need to provide some sort of synchronization so that there's no retain/release race conditions but thinking about it, taking ownership of an object should probably never be asynchronous.
My personal opinion is that anyone who puts this code into production should probably be fired or sued =P. But if it's only for educational purposes, have fun, and hope this helps.

Calling a block from within an inner block

I have a Cocoa/Objective-C class with a method that looks something like this:
- (void)doWork:(void (^)(void))handler
{
[self->someObject doActualWork:kWorkID handler:^(Result *result) {
if (handler)
handler();
}];
}
However, when the inner block is called handler have been dealloced and the program crashes when it is called. From what I understand this is because the block is stored on the stack and thus removed soon after doWork: finishes. I'm using ARC. What should I do to fix this?
First, self-> for iVar access is an odd, and discouraged, pattern, generally.
Did you copy the blocks prior to storing 'em away for use later? If this is intended to be asynchronous code, then your actualWork:handler: method should be copying the block prior to enqueueing it.
Even under ARC; while ARC handles the return of blocks from methods automatically, it can't handle blocks as arguments automatically and you do still need to copy 'em.
If this is purely synchronous code, then something else is going wrong. You'll need to provide more clues.

What does #synchronized() do as a singleton method in objective C?

I just created a singleton method, and I would like to know what the function #synchronized() does, as I use it frequently, but do not know the meaning.
It declares a critical section around the code block. In multithreaded code, #synchronized guarantees that only one thread can be executing that code in the block at any given time.
If you aren't aware of what it does, then your application probably isn't multithreaded, and you probably don't need to use it (especially if the singleton itself isn't thread-safe).
Edit: Adding some more information that wasn't in the original answer from 2011.
The #synchronized directive prevents multiple threads from entering any region of code that is protected by a #synchronized directive referring to the same object. The object passed to the #synchronized directive is the object that is used as the "lock." Two threads can be in the same protected region of code if a different object is used as the lock, and you can also guard two completely different regions of code using the same object as the lock.
Also, if you happen to pass nil as the lock object, no lock will be taken at all.
From the Apple documentation here and here:
The #synchronized directive is a
convenient way to create mutex locks
on the fly in Objective-C code. The
#synchronized directive does what any
other mutex lock would do—it prevents
different threads from acquiring the
same lock at the same time.
The documentation provides a wealth of information on this subject. It's worth taking the time to read through it, especially given that you've been using it without knowing what it's doing.
The #synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code.
The #synchronized directive does what any other mutex lock would do—it prevents different threads from acquiring the same lock at the same time.
Syntax:
#synchronized(key)
{
// thread-safe code
}
Example:
-(void)AppendExisting:(NSString*)val
{
#synchronized (oldValue) {
[oldValue stringByAppendingFormat:#"-%#",val];
}
}
Now the above code is perfectly thread safe..Now Multiple threads can change the value.
The above is just an obscure example...
#synchronized block automatically handles locking and unlocking for you. #synchronize
you have an implicit lock associated with the object you are using to synchronize. Here is very informative discussion on this topic please follow How does #synchronized lock/unlock in Objective-C?
Excellent answer here:
Help understanding class method returning singleton
with further explanation of the process of creating a singleton.
#synchronized is thread safe mechanism. Piece of code written inside this function becomes the part of critical section, to which only one thread can execute at a time.
#synchronize applies the lock implicitly whereas NSLock applies it explicitly.
It only assures the thread safety, not guarantees that. What I mean is you hire an expert driver for you car, still it doesn't guarantees car wont meet an accident. However probability remains the slightest.

#synchronized in a static method

In Objective-C, you can declare a block as being synchronized on some object by using the #synchronized construct. It would look something like this:
#synchronized (self) {
// Do something useful
}
However, I'm curious what exactly self is referring to when you have a static method (+ instead of -). I tried looking through the Apple docs, and they allude to it being OK, but don't really explain it. I know it works, I'm just curious what it means.
self inside of a class (static) method refers to the class object.
In Objective-C self is determined by context. In an instance method, that would be the instance being called. In a static method, it would be the class object itself (i.e. the result of [self class] in an instance method)
With the answers above, just keep in mind that if one thread calls an instance method using #synchronized (self), and another thread calls a class method using #synchronized (self), no synchronisation will happen between the two calls, because they are using different objects for synchronisation.