2015-02-02 3 views
4

Какие альтернативы нужно выполнить для следующего кода для выполнения безопасных асинхронных обратных вызовов на объекте?Шаблон для безопасных асинхронных обратных вызовов в C++

class MyClass : public std::enable_shared_from_this<MyClass> 
{ 
private: 

    void fetchResults() 
    { 
     std::weak_ptr<MyClass> weakSelf = shared_from_this(); 

     m_service.getResultAsync(
      /* args... */, 
      /* Callback */ 
      [weakSelf](Result r) 
      { 
       auto self = weakSelf.lock(); 
       if (self) 
       { 
        self->workFinishedWithResult(std::move(r)); 
       } 
      }); 
    } 

    void workFinishedWithResult(Result r) { // ... continue workflow } 

    std::shared_ptr<Service> m_service; 
}; 

Я хотел бы избежать использования enable_shared_from_this (и избежать клиентов m_service требуя его за то, что это очень распространенный способ использования), но мне кажется, трудно продлить срок службы MyClass один раз внутри обратного вызова без него.

Захват this в лямбда вместо этого и попытка отменить его в деструкторе MyClass или предотвратить разрушение MyClass до завершения обратного вызова - это путь, который ведет к расам, тупикам и потере простоты. Я почти уверен, что захват «этого» не может быть безопасным.

Кажется, что если MyClass просит shared_ptr<Service> позвонить ему, это может гарантировать, что оно остается в силе, если оно может управлять или продлевать его собственное время жизни (через enable_shared_from_this), поскольку оно не знает, как долго будет работать обратный вызов для. В противном случае это должно быть ответственностью того, кто владеет MyClass, или тем, кто знает всю жизнь как Service, так и MyClass, чтобы справиться с этим, но все это становится очень подверженным ошибкам и непрактичным.

кажется только жизнеспособные решения:

  • Использование enable_shared_from_this с рисунком «захватить слабо» (как в приведенном выше коде)
  • Have MyClass быть дан Service& поэтому ответственность абонента в убедитесь, что услуга переживает это.
  • Используйте статический метод/функцию в качестве обратного вызова и передайте все, что ему нужно, по значению (проблема в том, что иногда вы действительно хотите передать управление обратно в MyClass, и у вас есть та же проблема).

Каковы альтернативы здесь? Или использование enable_shared_from_this просто становится неизбежным при выполнении async C++?

ответ

1

Точная вещь, которую вы ищете, будет std::future<T>::then(). Он не существует в C++ 11, но boost :: future предлагает его.

Однако, в общем случае, абоненту будет гарантировано, что службы и экземпляры MyClass проживают достаточно долго, хотя это было бы также приемлемо, если метод получает ссылку на службу для владельца.

Смежные вопросы