Created
June 20, 2019 07:43
-
-
Save erwinv/6045a2c3c2bb2c7d0cbce1a87784cf4b to your computer and use it in GitHub Desktop.
How to correctly capture subscription pointer returned by service on the susbcription callback
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
#include <iostream> | |
#include <memory> | |
#include <deque> | |
class Subscription | |
{ | |
public: | |
Subscription() : active_(true) | |
{ | |
std::cout << "Subscribing..." << std::endl; | |
} | |
~Subscription() | |
{ | |
terminate(); | |
} | |
void terminate() { | |
if (active_) | |
{ | |
std::cout << "Unsubscribing..." << std::endl; | |
active_ = false; | |
} | |
} | |
private: | |
bool active_; | |
}; | |
using SubscriptionPtr = std::shared_ptr<Subscription>; | |
using Subscriber = std::function<void()>; | |
class Service | |
{ | |
public: | |
void notifyAll() | |
{ | |
while (not subscribers_.empty()) | |
{ | |
auto subscriber = subscribers_.front(); | |
subscribers_.pop_front(); | |
subscriber(); | |
} | |
} | |
SubscriptionPtr subscribe(Subscriber subscriber) | |
{ | |
subscribers_.emplace_back(subscriber); | |
return std::make_shared<Subscription>(); | |
} | |
private: | |
using Subscribers = std::deque<Subscriber>; | |
Subscribers subscribers_; | |
}; | |
using ServicePtr = std::unique_ptr<Service>; | |
int main() | |
{ | |
{ | |
std::cout << "start service scope" << std::endl; | |
ServicePtr service = std::make_unique<Service>(); | |
{ | |
std::cout << "start subscribe call scope" << std::endl; | |
// this doesn't work | |
// lambda closure capture by value happens first | |
// SubscriptionPtr subscription = service->subscribe([=]() { | |
// subscription->terminate(); | |
// }); | |
// this works ;) | |
// just add an extra layer/level of indirection | |
auto subscriptionContainer = std::make_shared<SubscriptionPtr>(); | |
SubscriptionPtr subscription = service->subscribe([=]() { | |
(*subscriptionContainer)->terminate(); | |
}); | |
*subscriptionContainer = subscription; | |
std::cout << "end subscribe call scope" << std::endl; | |
} | |
service->notifyAll(); | |
std::cout << "end service scope" << std::endl; | |
} | |
std::cout << "end main" << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment