异步任务已经完成时如何调用函数?

how to call a function when an asynchronous task is already done?

我有一套类是这样的:

class A {
public: 
   std::unique_ptr<B> b; 
   void triggerAsynchronously() {
       // this work is submitted to a queue. 
       b->getC()->signalAsync(); 
   }
}; 

class B {
public: 
   std::shared_ptr<C> c;
   std::shared_ptr<C> getC() const {
     return c; 
   }
   void doSomethingWithSignalFromClassC() {}
};

class C {
public: 
  void signalAsync() {
    // This function is submitted to a queue, and wait until its turn to be executed. 
    // I want to trigger A::b::doSomethingWithSignalFromC() once this function is done (aka end of this block)
  }
}

C::signalAsync()A::triggerSignalCAsynchronously() 触发。注意A::triggerSignalCAsynchronously()returns提交作品到队列后立即执行,但C::signalAsync()并没有立即执行。一旦 C::signalAsync() 被执行并完成它的工作,它应该通知 A::b::doSomethingWithSignalFromClassC().

我的问题是:当C::signalAsync()已经完成时如何通知B?从A,我们可以得到一个shared_pointer<C>。因此,自然的做法是将weak_ptr<B>存储在C中。但是,这不起作用,因为 b 是一个唯一指针。我还考虑在 C 中存储 B 的原始指针,但这似乎违背了 unique_ptr 设计。

此外,在 C 中存储指向 A 的原始指针似乎是错误的:

class A {
  void setA() {
    b->getC()->setA(this); 
  }
}

我感觉我的设计有问题。如果是你来解决这个问题,你会尝试哪些方向?

您需要非常准确地说明您的要求。你说

Once C::signalAsync() is executed and done with its work, it should notify A::b::doSomethingWithSignalFromClassC()

'Notify' 暗示线程正在某处等待被唤醒做某事 - 这很复杂

但您也可以表示,我希望 singalAsync 调用 B 实例上的方法。这很简单。

不知道这些调用的限制(你不会全部调用还是库中有一些你无法更改等)使它变得更难。

这是我要为回调案例做的事情

class C {
    std::shared_ptr<B> callback_;
public:
    C(std::shared_ptr<B> &cb){
         callback_ = cb;
    }
    void signalAsync() {
        // noodle noodle noodle
        callback_->doSomethingWithSignalFromClassC();
  }
}

即当我构造一个 C 对象时告诉它要回调的对象。

或者,您可以将其作为参数传递给 signalAsync,但也许那是不可能的

另一个想法是在构造函数中传递 std::function,这样您就不必硬编码在 signalAsync

结束时调用的方法

根据 pm100 的 answerstd::function 的用法确实有效。我想写下我最后做了什么,以防万一有人需要它。更详细一点,在我的例子中,C 的 header 文件不能包含 B 的 header 文件,因为 B 已经包含 C 在其 header 中(前向声明无效)。 C 也不能包含 A,因为 A 被设计为一个实现 class(指向实现的指针);因此,A header 位于 src 文件夹内,不应包含在任何地方(A.cc 除外)

我最后做了什么:

class A {
public: 
   std::unique_ptr<B> b; 
   void triggerAsynchronously() {
       // this work is submitted to a queue. 
       b->getC()->signalAsync(); 
   }
   void setFunctionToC() {
       // This happens before triggerAsynchronously()
       auto do_something_when_finished = [&b = b]() {
          b->doSomethingWithSignalFromClassC(); 
       }
       b->getC()->setFunctionToC(do_something_when_finished); 
   }
}; 

class C {
    std::function<void()> call_on_finished; 
public: 
  void setFunctionToC(std::function<void()> f) {
       call_on_finished = f; 
   }
  void signalAsync() {
    // This function is submitted to a queue, and wait until its turn to be executed. 
    // I want to trigger A::b::doSomethingWithSignalFromC() once this function is done (aka end of this block)
     call_on_finished(); 
  }
}