"Multi-threading" w/ NSTimers in an iPhone app - iphone

Say I have two NSTimers in my iPhone app: timer1 and timer2. timer1 calls function1 30 times per second and timer2 calls function2 30 times per second. Assume these two functions are reading and updating the same integer variables. Are there any "multi-threading" issues here? If not how does iPhone OS handle the execution of the two functions (in general)?

The core of any iPhone application (and some other platforms) is a run loop. Each thread may have a run loop, and the run loop on the main thread is set up for you. When there is something to do, like fire an NSTimer or draw the view hierarchy, the run loop performs those tasks. When there is nothing to do, the run loop is idle, allowing other things to process.
The run loop internals are thread aware so that nothing handled by the run loop has to be. All the NSTimer callbacks and view rendering happens on a single thread in a serial or linear flow.
For specific details, you can look up NSRunLoop or CFRunLoop.

As far as I'm aware, NSTimers use the run loop to achieve their 'asynchronosity'. If the timer is created using the scheduledTimerWith... method then it will be scheduled on the default (main) run loop and will be executed on the main thread.
I don't think any new threads are created for the timer (unless you do it explicitly, and assign the timer to that run loop).
So in the end, I believe your two timers shouldn't conflict with each other.
However, the documentation states that timers don't represent real time. The timer will fire on or after the scheduled time, but is not guaranteed to fire exactly at the scheduled time. Therefore if the fired method takes longer to execute than the interval of the timer, you may not see the method called as often as you'd expect.
With that said, is there any particular reason you're asking the question? Are you seeing undesired behaviour using this setup?

Related

Difference between DispatchSourceTimer, Timer and asyncAfter?

I am struggling to understand the key differences between DispatchSourceTimer, Timer and asyncAfter (in my case for scheduling a task that needs to be ran every X seconds, although understanding the differences in timers can be useful to) (Or is there another (more efficient) scheduling mechanism in Swift besides the listed timers?).
A Timer needs an active run loop on the current queue it was started on. A DispatchSourceTimer does not need that. A Timer keeps the CPU from going into the idle state. Does this apply to DispatchSourceTimer/asyncAfter as well?
In what situation a Timer is preferred over a DispatchSourceTimer/asyncAfter? And of course the difference between all of them?
I want to schedule work every 15 seconds in my application on a private queue. This means I have to use DispatchSourceTimer because I am on a queue that is not the main thread (or add a runloop to the queue and use Timer). However, I do not see any benefit of even using a Timer in the first place. Maybe there is another operation that I can use that schedule work every X seconds on a private queue that is more efficient than a DispatchSourceTimer, but I did not came across a better solution.
Is a DispatchSourceTimer more efficient than a Timer? Or should I go on a self-calling method with asyncAfter?
This is the code to create the timers.
asyncAfter
DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(2)) {
// Code
}
Timer
Timer.scheduledTimer(withTimeInterval: 1, repeats: false) { (_) in
// Code
}
DispatchSourceTimer
let timer = DispatchSource.makeTimerSource()
timer.schedule(deadline: .now() + .seconds(1))
timer.setEventHandler {
// Code
}
timer.activate()
Whats are the cons and pros of all the timers? When should I use one above the other? What timer way is the most efficient? I came up with the following:
Timer
Pros:
Can be invalidated
No reference needed
Can be stopped while it is scheduled.
Cons:
Prevents CPU to go idle
Needs to be run on a queue with a run loop (else nothing happens, even no assertion trigger...)
DispatchSourceTimer
Pros:
Can be cancelled
No run loop needed
Cons:
Needs a strong reference else it gets deallocated instantly
asyncAfter
Pros:
- No run loop needed
Cons:
- Can not be cancelled (I think)
Are there even more timers? Why are there so many timers? I expected some real difference across all the different timers, but I couldn't find them.
Alot of questions here as you can read. The main question is: what timers are available and what timers should I use in what case and why?
Timer is a Swift bridge of NSTimer, which goes back to NeXTSTEP, long, long before Grand Central Dispatch (GCD) and things like DispatchSourceTimer, which didn't come along until 10.6 (in the form of dispatch_source_set_timer) and dispatchAfter (in the form of dispatch_after).
NSTimer is based on the run loop, which was the primary way that concurrency was done until GCD. It's a cooperative concurrency system, designed primary to run on a single thread on a single core (though it can be expanded to multi-threaded environments).
While the run loop is still very important in Cocoa, it is no longer the primary, or even preferred, way to manage concurrency. Since 10.6, GCD has been the increasingly preferred approach (though adding a block-based NSTimer API in the 10.12 timeframe was a welcome modernization).
On the scale of 15 seconds, the efficiency differences are pretty irrelevant. That said, I don't understand your comment "A Timer keeps the CPU from going into the idle state." I don't believe that's true. The CPU will definitely still go into the idle state when waiting on an NSTimer to fire.
I would not set up a run loop just to run an NSTimer. You would be much better off scheduling it on the main runloop and then using DispatchQueue.async to do the actual work on some other queue.
As a broad rule, I use the highest-level tool that meets the need. Those are the ones that Apple is likely to optimize the best over time with me making the fewest changes. For example, NSTimer fire dates are automatically adjusted to improve energy efficiency. With DispatchSourceTimer, you get control over the leeway setting to get the same benefit, but it's up to you to set it (the default is zero, which has the worst energy impact). Of course, the reverse is also true. DispatchSourceTimer is the lowest level and gives you the most control, so if that's what you need, that's the one to use.
For your example, I'd personally probably use a Timer and just dispatch to the private queue as part of the block. But a DispatchSourceTimer would be completely appropriate.
asyncAfter is really a different thing, since it's always a one-shot. That's great if you want a one-shot, but it changes things if you want to repeat. If you just call asyncAfter in the block to repeat, it's going to be 15 seconds after the last time you finished, rather than being spaced 15 seconds apart. The former will tend to drift a bit late over time. The design question is this: if for some reason your task took 5 seconds to complete, would you want the next fire event to happen 15 seconds from the end of that, or would you want a constant 15 seconds between each fire event? Your choice there will determine which tool is correct.
As a slight note there, NSTimer events are always a little later than they are scheduled. GCD events with a leeway setting can be a little early or a little late. As a practical matter, there's no such thing as being "on time" (that's a period of zero length; you're not going to hit it). So the question is always whether you are promised to be late like NSTimer, or you might be early like GCD with leeway.

Networking using run loop

I have an application which uses some external library for analytics. Problem is that I suspect it does some things synchronously, which blocks my thread and makes watchdog kill my app after 10 secs (0x8badf00d code). It is really hard to reproduce (I cannot), but there are quite few cases "in the wild".
I've read some documentation, which suggested that instead creating another thread I should use run-loops. Unfortunately the more I read about them, the more confused I get. And the last thing i want to do is release a fix which will break even more things :/
What I am trying to achieve is:
From main thread add a task to the run-loop, which calls just one function: initMyAnalytics(). My thread continues running, even if initMyAnalytics() gets locked waiting for network data. After initMyAnalytics() finishes, it quietly quits and never gets called again (so it doesnt loop or anything).
Any ideas how to achieve it? Code examples are welcome ;)
Regards!
You don't need to use a run loop in that case. Run loops' purpose is to proceed events from various sources sequentially in a particular thread and stay idle when they have nothing to do. Of course, you can detach a thread, create a run loop, add a source for your function and run the run loop until the function ends. The same as you can use a semi-trailer truck to carry your groceries home.
Here, what you need are dispatch queues. Dispatch queues are First-In-First-Out data structures that run tasks asynchronously. In contrary to run loops, a dispatch queue isn't tied to a particular thread: the working threads are automatically created and terminated as and when required.
As you only have one task to execute, you don't need to create a dispatch queue. Instead you will use an existing global concurrent queue. A concurrent queue execute one or more tasks concurrently, which is perfectly fine in our case. But if we had many tasks to execute and wanted each task to wait for its predecessor to end, we would need to create a serial queue.
So all you have to do is:
create a task for your function by enclosing it into a Block
get a global queue using dispatch_get_global_queue
add the task to the queue using dispatch_async.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
initMyAnalytics();
});
DISPATCH_QUEUE_PRIORITY_DEFAULT is a macro that evaluates to 0. You can get different global queues with different priorities. The second parameter is reserved for future use and should always be 0.

Objective C, one method at a time?

If I make a simple Xcode project in cocos2d I've always wondered what happens in the following situation:
Method A is scheduled every 0.01 seconds
Method B is scheduled every 1 second
Now suppose method B is a large method and takes a moment to compute. Will it EVER be interrupted by method A?
In other words, will a method always complete before another one starts?
I havn't created threads or anything.
In general, when you're scheduling stuff in the UI thread of a UI application, once a specific operation is started, it's not interrupted (except for errors). This holds not only for iOS, but for most UI platforms.
The system may interrupt the UI thread to handle hardware interrupts (or, eg, interrupts due to received cell signals), but those interruptions would be (mostly) "transparent" to the application.
But you'll never be interrupted by your own operations.
This assumes you would be using, say, an NSTimer to schedule your methods AND both methods will be processing on the same runloop (i.e. not using seperate threads per method which is typically done when you want to schedule two methods to run independantly).
This quote taken directly from the NSTimer class reference overview section on apple's site:
If a timer’s firing time occurs during a long callout or while the run loop is in a mode that is not monitoring the timer, the timer does
not fire until the next time the run loop checks the timer.
Therefore, the actual time at which the timer fires potentially can be
a significant period of time after the scheduled firing time.
That is to say that Method A's polling mechanism (NSTimer for example) will not fire until Method B has completed assuming they are on the same run loop. Method A would not interrupt Method B, per sé, but is dependent on it completing its task.
If you want information on placing Method A and Method B on separate thread so they work independently, you can start here: Grand Central Dispatch
If you are not using threads, your methods are guaranteed to be executed sequentially, without interruptions.

what is the difference among sleep() , usleep() & [NSThread sleepForTimeInterval:]?

Can any body explain me what is the difference among sleep() , usleep() & [NSThread sleepForTimeInterval:] ?
What is the best condition to use these methods ?
sleep(3) is a posix standard library method that attempts to suspend the calling thread for the amount of time specified in seconds. usleep(3) does the same, except it takes a time in microseconds instead. Both are actually implemented with the nanosleep(2) system call.
The last method does the same thing except that it is part of the Foundation framework rather than being a C library call. It takes an NSTimeInterval that represents the amount of time to be slept as a double indicating seconds and fractions of a second.
For all intents and purposes, they all do functionally the same thing, i.e., attempt to suspend the calling thread for some specified amount of time.
What is the best condition to use
these methods ?
Never
Or, really, pretty much almost assuredly never ever outside of the most unique of circumstances.
What are you trying to do?
On most OSs, sleep(0) and its variants can be used to improve efficiency in a polling situation to give other threads a chance to work until the thread scheduler decides to wake up the polling thread. It beats a full-on while loop. I haven't found much use for a non-zero timeout though, and apple in particular has done a pretty good job of building an event driven architecture that should eliminate the need for polling in most situations anyway.
-Example usage of sleep is in the following state:
In network simulation scenario, we usually have events that are executed event by event,using a scheduler. The scheduler executes events in orderly fashion.
When an event is finished executing, and the scheduler moves to the next event, the scheduler compares the next event execution time with the machine clock. If the next event is scheduled for a future time, the simulator sleeps until that realtime is reached and then executes the next event.
-From linux Man pages:
The usleep() function suspends execution of the calling thread for (at least) usec microseconds. The sleep may be lengthened slightly by any system activity or by the time spent processing the call or by the granularity of system timers.
while sleep is delaying the execution of a task(could be a thread or anything) for sometime .Refer to 1 and 2 for more details about the functions.

Using NSTimer to get accurate timings

I need to run my game loop with very accurate timing. I am trying to use NSTimer to do this, and I am getting ok results, but there is a bit of drift.
When NSTimer fires does the next time event start counting when the handler finishes or does it start counting straight away.
If the former is it reasonable for me to use setFireDate to try to offset the next timer firing - when I tried this things seemed worse.
My timer is set to fire every 44ms and I would like to stop it drifting by more than 20ms. If it does drift I would like to correct it for the next fire.
Is this a reasonable thing to try and do with NSTimer?
I don't think NSTimer will give you "very" accurate timing. It fires on the run loop, so if it's in your main thread then it'll get delayed by everything from UI updates to event handling.
You might try creating a thread and scheduling your timer on that thread's run loop. Having that timer as the only thing on that run loop should limit the number of things that can interfere with it.
If that doesn't work, well, you'll already have it working on a thread, so you may as well switch to a usleep() loop.
Also keep in mind that the NSTimer documentation states:
Because of the various input sources a
typical run loop manages, the
effective resolution of the time
interval for a timer is limited to on
the order of 50-100 milliseconds. If a
timer’s firing time occurs while the
run loop is in a mode that is not
monitoring the timer or during a long
callout, the timer does not fire until
the next time the run loop checks the
timer. Therefore, the actual time at
which the timer fires potentially can
be a significant period of time after
the scheduled firing time.