-2
class Sample
{
  int a = 0;
  public void Run()
  {
     // main thread.Assuming this is chromium task runner.
     auto currentRunner = GetCurrentDefault();
     somePooledRunner->PostTask(
     [currentRunner, this]()
     {
        a = TimeConsumingOperation();
        // post back to main thread.
        currentRunner->PostTask([this]()
        {
            OnComplete1(a);
            OnComplete2();
        });
     });
  }
  
  void OnComplete1(int aParameter)
  {
      Process(aParameter);
  }
  
  void OnComplete2()
  {
     Process(this->a); // Is there a data visibility issue here that I'm overlooking but is being handled correctly by the library I'm using?
  }
}

This is similar to SynchronizationContext.Post for async/await. The lockfree or lock-based implementation of task queues helps me handle these issues correctly. But when I put aside these and face this problem, I wonder if there is really a problem here.

class SimpleSample
{
    int a = 0;
    void Run()
    {
        auto t = std::thread([this]()
            {
                a = TimeConsumingOperation();
            });

        t.detach();
        // To simplify the problem, no synchronization mechanism is introduced, and only sleep is performed. 
        Sleep(enoughTime);
        // Assume that the sleep time is sufficient for TimeConsumingOperation to complete and write a in worker thread. Is there a possibility that I cannot obtain the calculation result of a due to data visibility?

        // printf(a);
        Process(a);
    }
}

Is there a possibility that I cannot obtain the calculation result of a due to data visibility, in SimpleSample?

A note: Thanks guys, but please don't offer suggestions on how to use asynchronous APIs; that's beside the point. I'm just trying to figure out if there's a data visibility issue here, so I'm not introducing any synchronization mechanisms or extra function calls.

13
  • 1
    Added the c++ tag because the base language tag should always be present. Commented Aug 22 at 4:39
  • 3
    Yes you have a problem : Detaching a thread is almost never a good idea. And so is adding "Sleep" to preventing race conditions. Never write that kind of code again. Learn about : thread.join, or std::jthread. Next steps std::condition_variable/std::mutex and lastly lock-free programming (hard) Commented Aug 22 at 4:45
  • 1
    There's likely enough synchronization baked into Sleep call - it usually trips into kernel mode and back, and that involves fences galore. Commented Aug 22 at 4:48
  • 3
    @IgorTandetnik and at the same time it is totally unmaintainable in the long run, so I would run away from solutions like this ;) Commented Aug 22 at 4:51
  • 1
    Also in your example you will never know when a finally has the correct calculated value so in that respect it will not work either. Some side notes : don't use printf, use std::print, the documentation for std::async. Commented Aug 22 at 5:40

1 Answer 1

0

When you want to calculate something on a background thread use std::future/std::async

#include <future>

int main()
{
    std::future<int> future = std::async(std::launch::async, []()
    { 
        return TimeConsumingOperation(); 
    };

        // do other things here
    
    int a = future.get();
    return a;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.