I have the following piece of code in a cocoa Application for OSX:
void *callbackInfo = NULL; // could put stream-specific data here.
FSEventStreamRef stream;
CFAbsoluteTime latency = 1.0; /* Latency in seconds */
/* Create the stream, passing in a callback */
stream = FSEventStreamCreate(NULL,
&mycallback,
callbackInfo,
pathsToWatch,
kFSEventStreamEventIdSinceNow, /* Or a previous event ID */
latency,
kFSEventStreamCreateFlagFileEvents//kFSEventStreamCreateFlagNone /* Flags explained in reference */
);
/* Create the stream before calling this. */
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(),kCFRunLoopDefaultMode);
FSEventStreamStart(stream);
CFRunLoopRun();
}
This code gets notified about files system changes and reacts accordingly (the callback function is not in the snippet).
My problem now is that the CFRunLoopRun() is blocking. I.e. the further execution of the code stops. However, I'm looking for a possibility that I can start the observation of file system changes but also stop it again (e.g. from another object).
One option that I thought of would be to only start the loop for a second and check for a global variable afterwards. However, I usually don't like global variables....
Does anybody here have a nice and handy idea, how this could be solved? Would it be a good idea to buy the overhead and put the execution into a separate thread?
Thanks in advance!
Norbert
CFRunLoopRun() runs the current run loop forever, until somebody registered in the runloop calls CFRunLoopStop(). This is not what you want to do unless you're doing something very fancy.
If you want to the FSEventStream callback to run, you just register it with the runloop and leave it, you don't have to do anything explicitly to the runloop after that, registering the even stream as a source is all you have to do.
If you want to stop observing the stream you call FSEventStreamStop() on it.
A Cocoa application has an implicit run loop, so just delete CFRunLoopRun();
Consider to use a dispatch queue via Grand Central Dispatch (GCD) rather than schedule the stream on a run loop
Related
Is there a standard nice way to call a blocking method with a timeout in Objective C? I want to be able to do:
// call [something blockingMethod];
// if it hasn't come back within 2 seconds, forget it
Thanks.
It is not possible to interrupt a function that is not designed to be interrupted. Doing so would generally cause data corruption and resource leaks.
The standard way to achieve what you're describing is to redesign blockingMethod so that it accepts a timeout or other cancelation mechanism.
If that's not possible, and it is required that you timeout blockingMethod, the standard approach is to fork a child process to run blockingMethod, and kill it (usually by sending SIGTERM) if it doesn't finish by the timeout. This is somewhat complex to implement in ObjC, and you'll need to also implement a mechanism to send the results back to the parent process. Since the operating system manages resources (memory, file handles, etc) at the process level, the only way to forcibly interrupt a function is to create a separate process for it. This still can lead to data corruption depending on what blockingMethod does, but it will work for a much larger set of problems.
Note that it's not generally possible to fork a process from non-Apple code on iOS, so this can't be done there.
As an example of what I mean by "data corruption," consider some simple code like:
[self.cache lock];
[self.cache removeObject: object];
[self.cache decrementCountOfObjects];
[self.cache unlock];
Now imagine that the process were forcibly terminated in the middle of this operation. What should happen? How does the cache get unlocked? How are the cache contents and the count reconciled? It's even possible that the object would be in the middle of being copied; then what? How would the system automatically deal with all of these issues unless blockingMethod were written with cancelation in mind?
How about using a semaphore? This can be locked across threads and then you can do something like
dispatch_semaphore_t s = dispatch_semaphore_create ( 0 );
// In a different thread or on some queue,
// fire up some process, when done signal
// the semaphore with
[ fire up thread ... some task, when done
dispatch_semaphore_signal( s );
... ]
// This waits 2 seconds for the semaphore
if ( dispatch_semaphore_wait( s, 2 ) )
{
// ... it hasn't come back after 2 seconds so 'forget it'
}
else
{
// ... you now have the semaphore within 2 seconds so 'do it'
}
// This waits forever, just for reference
dispatch_semaphore_wait( s, DISPATCH_TIME_FOREVER );
Having moved some embedded code to FreeRTOS, I'm left with an interesting dilemma about the watchdog. The watchdog timer is a must for our application. Using FreeRTOS has been a huge boon for us too. When the application was more single-tasked, it fed the watchdog at timely points in its logic flow so that we could make sure the task was making logical progress in a timely fashion.
With multiple tasks though, that's not easy. One task could be bound up for some reason, not making progress, but another is doing just fine and making enough progress to keep the watchdog fed happily.
One thought was to launch a separate task solely to feed the watchdog, and then use some counters that the other tasks increment regularly, when the watchdog task ticks, it would make sure that all the counters looked like progress was being made on all the other tasks, and if so, go ahead and feed the watchdog.
I'm curious what others have done in situations like this?
A watchdog task that monitors the status of all the other tasks is a good solution. But instead of a counter, consider using a status flag for each task. The status flag should have three possible values: UNKNOWN, ALIVE, and ASLEEP. When a periodic task runs, it sets the flag to ALIVE. Tasks that block on an asynchronous event should set their flag to ASLEEP before they block and ALIVE when the run. When the watchdog monitor task runs it should kick the watchdog if every task is either ALIVE or ASLEEP. Then the watchdog monitor task should set all of the ALIVE flags to UNKNOWN. (ASLEEP flags should remain ASLEEP.) The tasks with the UNKNOWN flag must run and set their flags to ALIVE or ASLEEP again before the monitor task will kick the watchdog again.
See the "Multitasking" section of this article for more details: http://www.embedded.com/design/debug-and-optimization/4402288/Watchdog-Timers
This is indeed a big pain with watchdog timers.
My boards have an LED on a GPIO line, so I flash that in a while/sleep loop, (750ms on, 250ms off), in a next-to-lowest priority thread, (lowest is idle thread which just goes onto low power mode in a loop). I have put a wdog feed in the LED-flash thread.
This helps with complete crashes and higher-priority threads that CPU loop, but doesn't help if the system deadlocks. Luckily, my message-passing designs do not deadlock, (well, not often, anyway:).
Do not forget to handle possible situation where tasks are deleted, or dormant for longer periods of time. If those tasks were previously checked in with a watchdog task, they also need to have a 'check out' mechanism.
In other words, the list of tasks for which a watchdog task is responsible should be dynamic, and it should be organized so that some wild code cannot easily delete the task from the list.
I know, easier said then done...
I've design the solution using the FreeRTOS timers:
SystemSupervisor SW Timer which feed the HW WD. FreeRTOS Failure
causes reset.
Each task creates "its own" SW timer with SystemReset function.
Each task responsible to "manually" reload its timer before it expired.
SystemReset function saves data before commiting a suiside
Here is some pseudo-code listing:
//---------------------------------
//
// System WD
//
void WD_init(void)
{
HW_WD_Init();
// Read Saved Failure data, Send to Monitor
// Create Monitor timer
xTimerCreate( "System WD", // Name
HW_WD_INTERVAL/2, // Reload value
TRUE, // Auto Reload
0, // Timed ID (Data per timer)
SYS_WD_Feed);
}
void SYS_WD_Feed(void)
{
HW_WD_Feed();
}
//-------------------------
// Tasks WD
//
WD_Handler WD_Create()
{
return xTimerCreate( "", // Name
100, // Dummy Reload value
FALSE, // Auto Reload
pxCurrentTCB, // Timed ID (Data per timer)
Task_WD_Reset);
}
Task_WD_Reset(pxTimer)
{
TaskHandler_t th = pvTimerGetTimerID(pxTimer)
// Save Task Name and Status
// Reset
}
Task_WD_Feed(WD_Handler, ms)
{
xTimerChangePeriod(WD_Handler, ms / portTICK_PERIOD_MS, 100);
}
First I create a serial queue like this
static dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL);
then, at some unknown point in time a task gets added to the queue like this
dispatch_async(queue, ^{
// do something, which takes some time
});
If the first task hasn't finished yet, the new task will wait until the first completes (that's of course what a serial queue is for).
But if I add 5 new tasks to the queue, while the original first one is still running, I don't want to execute new task no.1, then no.2, then no.3 and so on, but want to get rid of tasks 1 to 4 and directly start executing task no.5 after the original first task has finished.
In other words, I want to pop any waiting task (not the one that is currently running) off the queue, if I add a new one.
Is there a build in mechanism for this or do I have to implement this myself? And for the latter, how would I identify single tasks inside a queue and remove them?
Once a block has been submitted to a GCD dispatch queue, it will run. There is no way to cancel it. You can, as you know, implement your own mechanism to "abort" the block execution early.
An easier way to do this would be to use NSOperationQueue, as it already provides an implementation for canceling pending operations (i.e., those not yet running), and you can easily enqueue a block with the new-ish addOperationWithBlock method.
Though NSOperationQueue is implemented using GCD, I find GCD much easier to use in most cases. However, in this case, I would seriously consider using NSOperationQueue because it already handles canceling pending operations.
With Davids answer getting me on track I succeeded in doing this like so
taskCounter++;
dispatch_async(queue, ^{
if (taskCounter > 1) {
taskCounter--;
NSLog(#"%#", #"skip");
return;
}
NSLog(#"%#", #"start");
// do stuff
sleep(3);
taskCounter--;
NSLog(#"%#", #"done");
});
taskCounter has to be either an ivar or a property (initialize it with 0). In that case it doesn't even need the __block attribute.
The way you handle this is to use an ivar that indicates to the queued blocks they should just return:
^{
if(!canceled) {
... do work
}
}
You don't need to use a simple boolean either - you can make this more complex - but the general idea is to use one or more ivars that the block queries before doing anything.
I use this technique (but did not invent it) with great success.
If instead of adding a closure in you add a DispatchWorkItem, you can cancel it as long as it hasn't started executing yet.
In the following code, backgroundWorkItem will never run, because it is cancelled before it starts executing.
let backgroundWorkItem = DispatchWorkItem {
print("Background work item executed")
}
DispatchQueue.main.async(execute: backgroundWorkItem)
backgroundWorkItem.cancel()
I ran into a scenario where I had a delegate callback which could occur on either the main thread or another thread, and I wouldn't know which until runtime (using StoreKit.framework).
I also had UI code that I needed to update in that callback which needed to happen before the function executed, so my initial thought was to have a function like this:
-(void) someDelegateCallback:(id) sender
{
dispatch_sync(dispatch_get_main_queue(), ^{
// ui update code here
});
// code here that depends upon the UI getting updated
}
That works great, when it is executed on the background thread. However, when executed on the main thread, the program comes to a deadlock.
That alone seems interesting to me, if I read the docs for dispatch_sync right, then I would expect it to just execute the block outright, not worrying about scheduling it into the runloop, as said here:
As an optimization, this function invokes the block on the current thread when possible.
But, that's not too big of a deal, it simply means a bit more typing, which lead me to this approach:
-(void) someDelegateCallBack:(id) sender
{
dispatch_block_t onMain = ^{
// update UI code here
};
if (dispatch_get_current_queue() == dispatch_get_main_queue())
onMain();
else
dispatch_sync(dispatch_get_main_queue(), onMain);
}
However, this seems a bit backwards. Was this a bug in the making of GCD, or is there something that I am missing in the docs?
dispatch_sync does two things:
queue a block
blocks the current thread until the block has finished running
Given that the main thread is a serial queue (which means it uses only one thread), if you run the following statement on the main queue:
dispatch_sync(dispatch_get_main_queue(), ^(){/*...*/});
the following events will happen:
dispatch_sync queues the block in the main queue.
dispatch_sync blocks the thread of the main queue until the block finishes executing.
dispatch_sync waits forever because the thread where the block is supposed to run is blocked.
The key to understanding this issue is that dispatch_sync does not execute blocks, it only queues them. Execution will happen on a future iteration of the run loop.
The following approach:
if (queueA == dispatch_get_current_queue()){
block();
} else {
dispatch_sync(queueA, block);
}
is perfectly fine, but be aware that it won't protect you from complex scenarios involving a hierarchy of queues. In such case, the current queue may be different than a previously blocked queue where you are trying to send your block. Example:
dispatch_sync(queueA, ^{
dispatch_sync(queueB, ^{
// dispatch_get_current_queue() is B, but A is blocked,
// so a dispatch_sync(A,b) will deadlock.
dispatch_sync(queueA, ^{
// some task
});
});
});
For complex cases, read/write key-value data in the dispatch queue:
dispatch_queue_t workerQ = dispatch_queue_create("com.meh.sometask", NULL);
dispatch_queue_t funnelQ = dispatch_queue_create("com.meh.funnel", NULL);
dispatch_set_target_queue(workerQ,funnelQ);
static int kKey;
// saves string "funnel" in funnelQ
CFStringRef tag = CFSTR("funnel");
dispatch_queue_set_specific(funnelQ,
&kKey,
(void*)tag,
(dispatch_function_t)CFRelease);
dispatch_sync(workerQ, ^{
// is funnelQ in the hierarchy of workerQ?
CFStringRef tag = dispatch_get_specific(&kKey);
if (tag){
dispatch_sync(funnelQ, ^{
// some task
});
} else {
// some task
}
});
Explanation:
I create a workerQ queue that points to a funnelQ queue. In real code this is useful if you have several “worker” queues and you want to resume/suspend all at once (which is achieved by resuming/updating their target funnelQ queue).
I may funnel my worker queues at any point in time, so to know if they are funneled or not, I tag funnelQ with the word "funnel".
Down the road I dispatch_sync something to workerQ, and for whatever reason I want to dispatch_sync to funnelQ, but avoiding a dispatch_sync to the current queue, so I check for the tag and act accordingly. Because the get walks up the hierarchy, the value won't be found in workerQ but it will be found in funnelQ. This is a way of finding out if any queue in the hierarchy is the one where we stored the value. And therefore, to prevent a dispatch_sync to the current queue.
If you are wondering about the functions that read/write context data, there are three:
dispatch_queue_set_specific: Write to a queue.
dispatch_queue_get_specific: Read from a queue.
dispatch_get_specific: Convenience function to read from the current queue.
The key is compared by pointer, and never dereferenced. The last parameter in the setter is a destructor to release the key.
If you are wondering about “pointing one queue to another”, it means exactly that. For example, I can point a queue A to the main queue, and it will cause all blocks in the queue A to run in the main queue (usually this is done for UI updates).
I found this in the documentation (last chapter):
Do not call the dispatch_sync function from a task that is executing
on the same queue that you pass to your function call. Doing so will
deadlock the queue. If you need to dispatch to the current queue, do
so asynchronously using the dispatch_async function.
Also, I followed the link that you provided and in the description of dispatch_sync I read this:
Calling this function and targeting the current queue results in deadlock.
So I don't think it's a problem with GCD, I think the only sensible approach is the one you invented after discovering the problem.
I know where your confusion comes from:
As an optimization, this function invokes the block on the current
thread when possible.
Careful, it says current thread.
Thread != Queue
A queue doesn't own a thread and a thread is not bound to a queue. There are threads and there are queues. Whenever a queue wants to run a block, it needs a thread but that won't always be the same thread. It just needs any thread for it (this may be a different one each time) and when it's done running blocks (for the moment), the same thread can now be used by a different queue.
The optimization this sentence talks about is about threads, not about queues. E.g. consider you have two serial queues, QueueA and QueueB and now you do the following:
dispatch_async(QueueA, ^{
someFunctionA(...);
dispatch_sync(QueueB, ^{
someFunctionB(...);
});
});
When QueueA runs the block, it will temporarily own a thread, any thread. someFunctionA(...) will execute on that thread. Now while doing the synchronous dispatch, QueueA cannot do anything else, it has to wait for the dispatch to finish. QueueB on the other hand, will also need a thread to run its block and execute someFunctionB(...). So either QueueA temporarily suspends its thread and QueueB uses some other thread to run the block or QueueA hands its thread over to QueueB (after all it won't need it anyway until the synchronous dispatch has finished) and QueueB directly uses the current thread of QueueA.
Needless to say that the last option is much faster as no thread switch is required. And this is the optimization the sentence talks about. So a dispatch_sync() to a different queue may not always cause a thread switch (different queue, maybe same thread).
But a dispatch_sync() still cannot happen to the same queue (same thread, yes, same queue, no). That's because a queue will execute block after block and when it currently executes a block, it won't execute another one until the currently executed is done. So it executes BlockA and BlockA does a dispatch_sync() of BlockB on the same queue. The queue won't run BlockB as long as it still runs BlockA, but running BlockA won't continue until BlockB has ran. See the problem? It's a classical deadlock.
The documentation clearly states that passing the current queue will cause a deadlock.
Now they don’t say why they designed things that way (except that it would actually take extra code to make it work), but I suspect the reason for doing things this way is because in this special case, blocks would be “jumping” the queue, i.e. in normal cases your block ends up running after all the other blocks on the queue have run but in this case it would run before.
This problem arises when you are trying to use GCD as a mutual exclusion mechanism, and this particular case is equivalent to using a recursive mutex. I don’t want to get into the argument about whether it’s better to use GCD or a traditional mutual exclusion API such as pthreads mutexes, or even whether it’s a good idea to use recursive mutexes; I’ll let others argue about that, but there is certainly a demand for this, particularly when it’s the main queue that you’re dealing with.
Personally, I think that dispatch_sync would be more useful if it supported this or if there was another function that provided the alternate behaviour. I would urge others that think so to file a bug report with Apple (as I have done, ID: 12668073).
You can write your own function to do the same, but it’s a bit of a hack:
// Like dispatch_sync but works on current queue
static inline void dispatch_synchronized (dispatch_queue_t queue,
dispatch_block_t block)
{
dispatch_queue_set_specific (queue, queue, (void *)1, NULL);
if (dispatch_get_specific (queue))
block ();
else
dispatch_sync (queue, block);
}
N.B. Previously, I had an example that used dispatch_get_current_queue() but that has now been deprecated.
Both dispatch_async and dispatch_sync perform push their action onto the desired queue. The action does not happen immediately; it happens on some future iteration of the run loop of the queue. The difference between dispatch_async and dispatch_sync is that dispatch_sync blocks the current queue until the action finishes.
Think about what happens when you execute something asynchronously on the current queue. Again, it does not happen immediately; it puts it in a FIFO queue, and it has to wait until after the current iteration of the run loop is done (and possibly also wait for other actions that were in the queue before you put this new action on).
Now you might ask, when performing an action on the current queue asynchronously, why not always just call the function directly, instead of wait until some future time. The answer is that there is a big difference between the two. A lot of times, you need to perform an action, but it needs to be performed after whatever side effects are performed by functions up the stack in the current iteration of the run loop; or you need to perform your action after some animation action that is already scheduled on the run loop, etc. That's why a lot of times you will see the code [obj performSelector:selector withObject:foo afterDelay:0] (yes, it's different from [obj performSelector:selector withObject:foo]).
As we said before, dispatch_sync is the same as dispatch_async, except that it blocks until the action is completed. So it's obvious why it would deadlock -- the block cannot execute until at least after the current iteration of the run loop is finished; but we are waiting for it to finish before continuing.
In theory it would be possible to make a special case for dispatch_sync for when it is the current thread, to execute it immediately. (Such a special case exists for performSelector:onThread:withObject:waitUntilDone:, when the thread is the current thread and waitUntilDone: is YES, it executes it immediately.) However, I guess Apple decided that it was better to have consistent behavior here regardless of queue.
Found from the following documentation.
https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html#//apple_ref/c/func/dispatch_sync
Unlike dispatch_async, "dispatch_sync" function does not return until the block has finished. Calling this function and targeting the current queue results in deadlock.
Unlike with dispatch_async, no retain is performed on the target queue. Because calls to this function are synchronous, it "borrows" the reference of the caller. Moreover, no Block_copy is performed on the block.
As an optimization, this function invokes the block on the current thread when possible.
A valuable answer will include the rpg code that does something like this
volatile bool interrupted;
main() {
sigaction(SIG_ALARM, myhandler) // register handler
alarm(3) // set the alarm
sleep(5) // blocking call, sleep just as an example.
alarm(0) // disable the alarm
}
myHandler() {
interrupted=true
}
I think you've got the idea.
I have a code that blocks, similar to sleep, and I want an alarm to unlock the blocking call
Another question, after the alarm handler has finished, where does the execution point goes ? does it terminate the program ?, can I call another method while inside myHandler() ? Is it allowed, how can I keep doing something before the program finishes, like log to a table till where did I went ?
Thank you very much !
This article gives some good examples of using signals (including SIG_ALARM) from ILE RPG:
http://systeminetwork.com/article/terminate-and-stay-residentin-rpg
If your program is running while SIG_ALARM is received, execution temporarily switches to the alarm handler. After the alarm handler is finished, execution resumes where it left off.
The example given in the link does QCMDEXC and file IO from the alarm handler, so it would seem like you can do just about anything there. (Though, his example had basically no mainline running that could be interfered with; in fact his alarm handler was running after the mainline ended!)