0

Imagine the following pattern: you have a window with information that needs to be updated asynchronously. You launch and detach a thread to handle fetching the information, but while the information is being fetched the window is closed and unloaded from memory. When the background thread goes to update the information in the window's memory, the memory has already been deallocated and a segmentation fault occurs.

I'm programming in C++, so I could wrap the memory being updated in a std::shared_ptr, but this means the memory has to stay allocated for the duration of the background task, and I'd rather free it immediately. Is there a better way to solve this problem?

5
  • 1
    Which GUI framework are you using, and how precisely do you intend to update the data in the window from a different thread than the GUI thread?
    – Doc Brown
    Commented Apr 10, 2020 at 17:37
  • @DocBrown The rendering and window logic (when to close the window, etc.) is done with ImGui, but this problem applies regardless of how the window is rendered IMO.
    – Omegastick
    Commented Apr 11, 2020 at 3:32
  • @DocBrown When spawning a thread, it has a pointer to a piece of memory and a flag to set when the operation is done, both of which are atomic or guarded with a mutex. When it is finished with the task it updates the memory at the pointer and sets the flag, letting the main thread know that the data is ready to be used.
    – Omegastick
    Commented Apr 11, 2020 at 3:34
  • Different GUI frameworks provide different kinds of event mechanics, which might be used to solve the issue here. However, I think for this case, it is straightforward that for sharing memory between two threads with no single owner, you need a shared_ptr, and for freeing the shared memory when the window is closed, it is obviously necessary to cancel the background thread beforehand. And that leads directly to rwong's answer.
    – Doc Brown
    Commented Apr 11, 2020 at 7:03
  • .. The details on how the window sends the background thread a "cancel" event are to some degree a matter of taste and can be done the way rwong suggested by using a boolean flag. Frameworks like Qt provide complete event systems on their own which could be an alternative .
    – Doc Brown
    Commented Apr 11, 2020 at 7:10

1 Answer 1

4

You can implement the task cancellation pattern.

You can find this pattern in Intel TBB, Microsoft C++ PPL, Microsoft C# TPL, and many other parallel frameworks.

The task cancellation pattern consist of shared flag and shared data. The flag itself can be implemented as a std::atomic<bool>. Either thread can set it. Any code that spends significant CPU time working on the data should check this flag occasionally, and to wrap up or abandon the work if it is set to true. In addition to wrapping up, it should also release the std::shared_ptr<T> to the shared data. Because the thread that requests cancellation is presumably also releasing the shared data, the outcome is that the shared data will indeed be released as quickly as possible after cancellation once both threads had time to acknowledge and respond to that.

In some cases, you may use std::weak_ptr<T>, if it is appropriate for some of the threads to unilaterally cause the data to be discarded. Note that, any code that want to access the data guarded by a std::weak_ptr<T> must do so by requesting and keeping a std::shared_ptr<T> from it during the access. Otherwise, there will be a multithreaded use-after-free race condition (freeing during use) defect.

There are other approaches, such as manager object, singleton (which is a static manager), message-passing architecture, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.