Skip to content

Instantly share code, notes, and snippets.

@erwinv
Created June 20, 2019 07:43
Show Gist options
  • Save erwinv/6045a2c3c2bb2c7d0cbce1a87784cf4b to your computer and use it in GitHub Desktop.
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
#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