| /* | |
| Copyright (c) 2017 Microsoft Corporation. All rights reserved. | |
| Released under Apache 2.0 license as described in the file LICENSE. | |
| Author: Gabriel Ebner | |
| */ | |
| #include "util/cancellable.h" | |
| #include <algorithm> | |
| namespace lean { | |
| cancellation_token_cell::cancellation_token_cell(cancellation_token const & parent) : | |
| m_cancelled(false), m_parent(parent) {} | |
| cancellation_token_cell::~cancellation_token_cell() { | |
| if (m_parent) m_parent->gc(); | |
| } | |
| void cancellation_token_cell::cancel(std::shared_ptr<cancellable> const &) { | |
| unique_lock<mutex> lock(m_mutex); | |
| m_cancelled.store(true); | |
| auto children = m_children; | |
| lock.unlock(); | |
| for (auto & child : children) | |
| cancelw(child); | |
| } | |
| void cancellation_token_cell::gc() { | |
| unique_lock<mutex> lock(m_mutex); | |
| m_expired_children++; | |
| if (m_expired_children > m_children.size()/2) { | |
| m_children.erase(std::remove_if(m_children.begin(), m_children.end(), | |
| [](std::weak_ptr<cancellable> const &c) { return c.expired(); }), | |
| m_children.end()); | |
| m_expired_children = 0; | |
| } | |
| } | |
| void cancellation_token_cell::add_child(std::weak_ptr<cancellable> const & c) { | |
| unique_lock<mutex> lock(m_mutex); | |
| m_children.push_back(c); | |
| if (m_cancelled.load()) { | |
| lock.unlock(); | |
| cancelw(c); | |
| } | |
| } | |
| cancellation_token mk_cancellation_token(cancellation_token const & parent) { | |
| auto ctok = std::make_shared<cancellation_token_cell>(parent); | |
| if (parent) parent->add_child(ctok); | |
| return ctok; | |
| } | |
| LEAN_THREAD_PTR(cancellation_token const, g_cancellation_token); | |
| scope_cancellation_token::scope_cancellation_token(cancellation_token const * tok) : | |
| flet<cancellation_token const *>(g_cancellation_token, tok), | |
| scoped_interrupt_flag(*tok ? (*tok)->get_cancellation_flag() : nullptr) { | |
| } | |
| cancellation_token global_cancellation_token() { | |
| return g_cancellation_token ? *g_cancellation_token : nullptr; | |
| } | |
| } |