I have a function that shoud run in a controlled amount of time. But this function uses pcl::StatisticalOutlierRemoval
and i didn't find any reasonable way to cancel the this function other than killing the thread arbitrarily.
I have something like this:
void cloud_filtering(pcl::PointCloud<pcl::PointXYZRGB>::SharedPtr pcl_unfilt, pcl::PointCloud<pcl::PointXYZRGB>::SharedPtr pcl_filt) const{
// do something
pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sor;
sor.setInputCloud(*pcl_unfilt);
sor.setMeanK(50);
sor.setStddevMulThresh(1.0);
sor.filter(*pcl_filt);
// do something
}
This function is executed by an independent thread that should have some timeout. The thread is launched using std::async and the completion is checked using the returned future.
auto future = std::async(
std::launch::async,
&cloud_filtering,this,pcl_unfilt,pcl_filt
)
Usually, this function is executed pretty fast, but not always, and I don't really need all the responses (It depends on the sampled input of the function). So what I want to do is, if the function takes more than a given timeout it gets safely canceled so I can launch a new thread with other samples.
By safely canceled I mean avoid memory leaks or zombie threads.
#include <future>
#include <chrono>
void cloud_filtering(pcl::PointCloud<pcl::PointXYZRGB>::SharedPtr pcl_unfilt, pcl::PointCloud<pcl::PointXYZRGB>::SharedPtr pcl_filt, std::promise<void>&& promise) const{
// do something
pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> sor;
sor.setInputCloud(*pcl_unfilt);
sor.setMeanK(50);
sor.setStddevMulThresh(1.0);
sor.filter(*pcl_filt);
// do something
promise.set_value(); // signal completion
}
// function to call with a timeout
bool cloud_filtering_with_timeout(pcl::PointCloud<pcl::PointXYZRGB>::SharedPtr pcl_unfilt, pcl::PointCloud<pcl::PointXYZRGB>::SharedPtr pcl_filt, int timeout_ms) {
std::promise<void> promise;
auto future = promise.get_future();
auto task = std::async(std::launch::async, &cloud_filtering, this, pcl_unfilt, pcl_filt, std::move(promise));
bool completed = false;
if (future.wait_for(std::chrono::milliseconds(timeout_ms)) == std::future_status::timeout) {
// timeout occurred, cancel task
task.get(); // this will call std::terminate() if the task is still running
completed = false;
} else {
completed = true;
}
return completed;
}
cloud_filtering_with_timeout
takes input point clouds + timeout in milliseconds -- returns boolean value(whether the function completed before the timeout or not)std::promise
signals cloud_filtering
completion -- std::future
waits for completion with timeout(timeout occurs before function completes -- task.get()
call will cancel the task - throws std::future_error
-- will be caught + ignored by std::async
)
PS. isn't a clean way to cancel pcl::StatisticalOutlierRemoval
but should avoid memory leaks and zombie threads