Checking status of std::future from other thread

36 Views Asked by At

We have a COM server that provides a scripting service to clients. A client may initiate a script and wait for the result, or it may initiate a script and not wait for the result.

In the cases where the client does not wait for the result, it will be interested in knowing when the script has completed execution. In many cases, the completion will be minutes later. Rather than waiting for the completion, the client will check back occasionally to see if the task is complete.

We launch the scripts as a std::async. We monitor the status using a std::future returned by the std::async.

The code looks something like this:

    class script_engine {

    public:

        bool is_busy(){
            // Question 1 concerns this line
            return _future.valid() && !(_future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready);
        };

        void abort(){ _abort = true; }

        Value eval_async(const std::string& expr, bool wait = false){
            // Question 2 concerns this line
            while (_future.valid() && !(_future.wait_for(std::chrono::milliseconds(10)) == std::future_status::ready));
            
            T retval{};
            _abort = false;

            // Question 3 concerns this line
            _future = _script->eval_file_async(file, [=] { return _abort; });  // <-- This function does std::async launch
            if (wait) {
                _future.wait();
                retval = _future.get();
            }
            return retval;
        }

    private:
        std::shared_ptr<script> _script;
        std::future<Value> _future;
        std::atomic_bool _abort{ false };
    };
}

There are other threads in our server that will call the is_busy(), and abort() functions.

Question 1: Is the is_busy() function thread safe? If not, is there a way to make it thread safe?

Question 2: Is the while(_future.valid()... line a conventional way to prevent a wrap-around collision?

Question 3: Is it valid to launch the async again, assigning to _future, without ever calling _future.get()?

Observation: This is somewhat an A vs B question. What we really want is a way to do what was initially described. A client should be able to launch a script, and either wait for the result, or not care about the result. Additionally the client needs to be able to tell when the script is done by occasionally polling.

0

There are 0 best solutions below