user3292642
user3292642

Reputation: 761

C++ when to check exceptions of async method

I'm stuck with executing a function async. For now the function is called synchronously. It stores some information on a list and provides information about the list items later.

// Read Infos
void MyManager::Read(HWND parent)
{
   // do some work...
   mItemInfos.push_back(info);
}

// provide information
ItemInfo* MyManager::GetInfo(int index)
{
  return mItemInfos.at(index);
}

Now I want to do the reading async. I defined a new method

void MyManager::BeginRead(HWND parent)
{
  mFuture = std::async(std::launch::async, &MyManager::Read, this, parent); 
}

Now when an exception is thrown in the Readmethod, i will never know, because the mFuture.get() method is never called. To fix this, should I just call mFuture.get() In GetInfo()? Everytime I call GetInfo()?

My whole approach seems to miss something, can anyone help me please?

Thanks in advance

Upvotes: 2

Views: 314

Answers (1)

JVApen
JVApen

Reputation: 11317

Looking at the code, I see multiple issues:

  • No mutexes around a std::vector while using it in multiple threads -> Race condition
  • Assigning to the future will block your program
  • You intend to call .get() multiple times on the same instance of future?

For std::future are only allowed to call .get() once. If you want to call it multiple times, you'll need std::shared_future which will throw every access.

So, should you call .get() before accessing the vector? Yes, definitely. Otherwise you don't have a guarantee that the element will be in the vector. However, you should also add some synchronization for access of the vector, as one thread could try to access it, while another creates a new future which reallocates the vector you are accessing.

Finally, why do you waste time with creating new threads? The operation itself looks cheap. Even when it isn't, I can only assume you don't want to block at that point. Unfortunately, you don't prevent blocking as the Dtor of the std::future will block in certain cases.

Again, using std::shared_future would prevent that, however, than you no longer have control about whether it was executed, as the second assignment lets mFuture forget about the first one, even when not fully executed.

Upvotes: 1

Related Questions