Hi John,
Jim’s reply didn’t include your attachment, so I haven’t looked at your code. However, I can give general answers to your questions.
We have a couple of calls of the form: pollScheduleNode = scheduler->scheduleUS(…); and I’d like to understand better how the MW scheduler works.
- If we use this type of call for a one-shot call (e.g., to turn off the juice), do we need to do any clean up for the scheduler?
No. If the task runs to completion, it will clean up after itself (i.e. remove itself from the scheduler). Your code is responsible for deallocating the ScheduleTask object, but you don’t need to notify the scheduler in any way.
- If we used this for a call that repeats indefinitely, what the correct way to stop and clean up? Is pollScheduleNode->cancel(); pollScheduleNode->kill(); what’s needed? All that’s needed?
If you want to stop a task that’s been scheduled to run indefinitely, the correct method to call is cancel(). This is all that’s needed to stop the task and remove it from the scheduler.
The kill() method is a last resort. It blindly calls pthread_cancel() to blow away the task’s thread, circumventing all normal cleanup and shutdown. It exists so that you can kill a task that’s become wedged (e.g. stuck waiting for I/O, or caught in an infinite loop). Practically speaking, you should never call it.
- IODevice provide stopAllScheduleNodes(), but it looks like that only cancels the scheduled nodes and then clears them. Does cancel free all the node resources, or is the kill also needed? What clears the node resources (i.e. at what point does our node pointer become dangling)?
The calls to cancel() stop each task, and the clear() call drops all schedule node references held by the IODevice base class. These references are shared_ptr instances, so if there is no other shared_ptr referencing a given node, then its destructor is called and its resources are released. However, if there are other shared_ptr instances that wrap a given node, then it is not deallocated until all such instances are released (i.e. they go out of scope, or you call their reset() method).
If your code is both adding nodes to IODevice’s schedule_nodes vector and keeping its own pointers to the nodes, then the pointers should be wrapped in shared_ptr instances. That way, even if you call stopAllScheduleNodes(), your pointers will still be valid, and the nodes won’t be deallocated until you release them.
FYI, the right way to add nodes to the schedule_nodes vector is as follows (where “node” is an instance of boost::shared_ptr):
schedule_nodes_lock.lock();
schedule_nodes.push_back(node);
schedule_nodes_lock.unlock();
I’ve attached a copy of the file in case that helps. We’ve also wondered whether we could be getting in trouble by using the wrong sort of shared pointers.
Once I have a copy of your code, I’ll take a look and see if I can spot any issues.
Chris