dimanche 25 février 2018

Sharing data between API and application threads

My API computes some data in its own thread:

/*** API is running in its own thread ***/
class API {
public:
    std::shared_ptr<Data> retrieveData() { return mData; }

private:
    std::shared_ptr<Data> mData;
    std::mutex mDataMutex;

    void run () {
        std::thread t([](){
            while (!exitApi) {
                mDataMutex.lock();

                updateData(mData);

                mDataMutex.unlock();
        });
        t.join();
    }
};

An application that uses our API will retrieve the shared data in another thread:

/*** Application is running in another thread ***/
class Application {
private:
    Api mApi;

    void run () {
        std::thread t([](){
            while (!exitApp) {
                std::shared_ptr<Data> data = mApi.retrieveData();

                /* API thread can update the data while the App is using it! */
                useData(data);
        });
        t.join();
    }

How can I ensure a secure exchange of the shared data between the two threads? I can think of three options but do not like any of them:

  1. Instead of sharing the pointer, the API will return a copy of all the data. However, the amount of data can get quite large and copying it should be avoided.
  2. The API will lock the data when it hands it over to the application and the application needs to explicitly ask the API to unlock it again after performing all computations. Even if documented correctly this is very much prone to deadlocks.
  3. When the API hands over the data to the application retrieveData will also return an already locked std::unique_lock. Once the application is done with using the data it has to unlock the unique_lock. This is potentially less prone to error but still not very obvious for the application developer.

Are there any better options to design the API (in modern C++11 and beyond) that is as developer-friendly as possible?

Aucun commentaire:

Enregistrer un commentaire