Какие альтернативы нужно выполнить для следующего кода для выполнения безопасных асинхронных обратных вызовов на объекте?Шаблон для безопасных асинхронных обратных вызовов в 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++?