c++multithreadingrospcl

Point Cloud Library (PCL) filtering timeout


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.


Solution

  • #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;
    }
    

    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