/* 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 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 const &) { unique_lock 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 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 const &c) { return c.expired(); }), m_children.end()); m_expired_children = 0; } } void cancellation_token_cell::add_child(std::weak_ptr const & c) { unique_lock 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(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(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; } }