#include #include #include #include #include namespace mbgl { BaseRequest::BaseRequest(const std::string &path_) : thread_id(uv_thread_self()), path(path_) { } BaseRequest::~BaseRequest() { assert(thread_id == uv_thread_self()); } void BaseRequest::notify() { assert(thread_id == uv_thread_self()); // The parameter exists solely so that any calls to ->remove() // are not going to cause deallocation of this object while this call is in progress. util::ptr retain = self; // Swap the lists so that it's safe for callbacks to call ->cancel() // on the request object, which would modify the list. std::forward_list> list; list.swap(callbacks); // Only notify when we actually have a response. When the response code is 0, the request was // canceled and we don't need to notify. if (response) { // Now that we have our private copy, notify all observers. for (std::unique_ptr &callback : list) { assert(callback); (*callback)(*response); } } self.reset(); } Callback *BaseRequest::add(Callback &&callback, const util::ptr &request) { assert(thread_id == uv_thread_self()); assert(this == request.get()); if (response) { // We already have a response. Notify right away. callback(*response); return nullptr; } else { self = request; callbacks.push_front(std::unique_ptr(new Callback(std::move(callback)))); return callbacks.front().get(); } } void BaseRequest::remove(Callback *callback) { assert(thread_id == uv_thread_self()); callbacks.remove_if([=](const std::unique_ptr &cb) { return cb.get() == callback; }); if (callbacks.empty()) { self.reset(); } } }