diff options
Diffstat (limited to 'src/libixion/formula_calc.cpp')
-rw-r--r-- | src/libixion/formula_calc.cpp | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/libixion/formula_calc.cpp b/src/libixion/formula_calc.cpp new file mode 100644 index 0000000..0e16382 --- /dev/null +++ b/src/libixion/formula_calc.cpp @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <ixion/formula.hpp> +#include <ixion/address.hpp> +#include <ixion/cell.hpp> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/model_context.hpp> + +#include "queue_entry.hpp" +#include "debug.hpp" + +#if IXION_THREADS +#include "cell_queue_manager.hpp" +#endif + +#include <algorithm> + +namespace ixion { + +namespace { + +class calc_scope +{ + model_context& m_cxt; +public: + calc_scope(model_context& cxt) : m_cxt(cxt) + { + m_cxt.notify(formula_event_t::calculation_begins); + } + + ~calc_scope() + { + m_cxt.notify(formula_event_t::calculation_ends); + } +}; + +} + +void calculate_sorted_cells( + model_context& cxt, const std::vector<abs_range_t>& formula_cells, size_t thread_count) +{ +#if IXION_THREADS == 0 + thread_count = 0; // threads are disabled thus not to be used. +#endif + + calc_scope cs(cxt); + + std::vector<queue_entry> entries; + entries.reserve(formula_cells.size()); + + for (const abs_range_t& r : formula_cells) + entries.emplace_back(cxt.get_formula_cell(r.first), r.first); + + // Reset cell status. + for (queue_entry& e : entries) + { + e.p->reset(); + IXION_TRACE("pos=" << e.pos.get_name() << " formula=" << detail::print_formula_expression(cxt, e.pos, *e.p)); + } + + // First, detect circular dependencies and mark those circular + // dependent cells with appropriate error flags. + for (queue_entry& e : entries) + e.p->check_circular(cxt, e.pos); + + if (!thread_count) + { + // Interpret cells using just a single thread. + for (queue_entry& e : entries) + e.p->interpret(cxt, e.pos); + + return; + } + +#if IXION_THREADS + // Interpret cells in topological order using threads. + formula_cell_queue queue(cxt, std::move(entries), thread_count); + queue.run(); +#endif +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |