Is this a reasonable way to achieve a "self-destructing" Timer?
I want to be able to fire off one-shot Timer events and not worry about cleaning up after the reference to the Timer object, which deletes the callback if it falls out of scope. I hadn't been able to find anything helpful on how to achieve this, so I came up with this pattern.
/// just for pretty-printing
std::string to_string(ros::Timer &t) {
std::stringstream ss;
ss << "Timer@" << &t << "(s=" << t.hasStarted() << ", p=" << t.hasPending() << ")";
return ss.str();
}
/// Create an anonymous timer callback. A reference to ros::Timer must exist in order for the callback
/// to trip. If the Timer is destructed, the callback is popped from the event queue
/// NodeHandle is ROS's god class. It handles the event queue, firing callbacks, message bus, etc.
void anonymous_timer(ros::NodeHandlePtr const &nhp, double duration) {
if (!ros::ok()) return;
auto yolo = std::make_shared<ros::Timer>();
auto func = [nhp, yolo](const ros::TimerEvent &event) {
ROS_INFO("inside callback %s", to_string(*yolo).c_str());
/// (yolo) falls out of scope here which should fully destruct the shared pointer
};
*yolo = nhp->createTimer(ros::Duration(duration), func, true, true);
/// (*yolo) would normally fall out of scope, but since we retained a shared_ptr (yolo) to it in the lambda, it survives
}
This achieves the behavior I want, and I've stressed tested this by allocating large strings to check for memory leaks, but I'm not sure that this isn't going to result in anything unexpected, such as a memory leak due to circular references preventing that shared_ptr from destructing. Gonna also try to valgrind it once I figure out how to valgrind a ros node, will update with results if I can.
Thanks,
Edit 1: I just ran a node which uses this mechanism to re-issue an event every second. After running for 8 hours, it's taking up to 12 seconds between firing, so something's definitely amiss. I want to be able to check the size or contents of the callback queue, but it seems like the API doesn't give me that level of access.