-void System::disable_var(Variable* var)
-{
- xbt_assert(not var->staged_weight, "Staged weight should have been cleared");
- // Disabling the variable, move to var to list tail. Subtlety is: here, we need to call update_modified_set
- // BEFORE moving the last element of var.
- simgrid::xbt::intrusive_erase(variable_set, *var);
- variable_set.push_back(*var);
- if (not var->cnsts.empty())
- update_modified_set(var->cnsts[0].constraint);
- for (Element& elem : var->cnsts) {
- simgrid::xbt::intrusive_erase(elem.constraint->enabled_element_set, elem);
- elem.constraint->disabled_element_set.push_back(elem);
- if (elem.active_element_set_hook.is_linked())
- simgrid::xbt::intrusive_erase(elem.constraint->active_element_set, elem);
- elem.decrease_concurrency();
- }
-
- var->sharing_weight = 0.0;
- var->staged_weight = 0.0;
- var->value = 0.0;
- check_concurrency();
-}
-
-/* /brief Find variables that can be enabled and enable them.
- *
- * Assuming that the variable has already been removed from non-zero weights
- * Can we find a staged variable to add?
- * If yes, check that none of the constraints that this variable is involved in is at the limit of its concurrency
- * And then add it to enabled variables
- */
-void System::on_disabled_var(Constraint* cnstr)
-{
- if (cnstr->get_concurrency_limit() < 0)
- return;
-
- int numelem = cnstr->disabled_element_set.size();
- if (not numelem)
- return;
-
- Element* elem = &cnstr->disabled_element_set.front();
-
- // Cannot use foreach loop, because System::enable_var() will modify disabled_element_set.. within the loop
- while (numelem-- && elem) {
-
- Element* nextelem;
- if (elem->disabled_element_set_hook.is_linked()) {
- auto iter = std::next(cnstr->disabled_element_set.iterator_to(*elem));
- nextelem = iter != std::end(cnstr->disabled_element_set) ? &*iter : nullptr;
- } else {
- nextelem = nullptr;
- }
-
- if (elem->variable->staged_weight > 0 && elem->variable->can_enable()) {
- // Found a staged variable
- // TODOLATER: Add random timing function to model reservation protocol fuzziness? Then how to make sure that
- // staged variables will eventually be called?
- enable_var(elem->variable);
- }
-
- xbt_assert(cnstr->concurrency_current <= cnstr->get_concurrency_limit(), "Concurrency overflow!");
- if (cnstr->concurrency_current == cnstr->get_concurrency_limit())
- break;
-
- elem = nextelem;
- }
-
- // We could get an assertion fail, because transiently there can be variables that are staged and could be activated.
- // And we need to go through all constraints of the disabled var before getting back a coherent state.
- // Anyway, caller functions all call check_concurrency() in the end.
-}
-
-/* \brief update the weight of a variable, and enable/disable it.
- * @return Returns whether a change was made
- */
-void System::update_variable_weight(Variable* var, double weight)
-{
- xbt_assert(weight >= 0, "Variable weight should not be negative!");
-
- if (weight == var->sharing_weight)
- return;
-
- int enabling_var = (weight > 0 && var->sharing_weight <= 0);
- int disabling_var = (weight <= 0 && var->sharing_weight > 0);
-
- XBT_IN("(sys=%p, var=%p, weight=%f)", this, var, weight);
-
- modified = true;
-
- // Are we enabling this variable?
- if (enabling_var) {
- var->staged_weight = weight;
- int minslack = var->get_min_concurrency_slack();
- if (minslack < var->concurrency_share) {
- XBT_DEBUG("Staging var (instead of enabling) because min concurrency slack %i, with weight %f and concurrency"
- " share %i",
- minslack, weight, var->concurrency_share);
- return;
- }
- XBT_DEBUG("Enabling var with min concurrency slack %i", minslack);
- enable_var(var);
- } else if (disabling_var) {
- // Are we disabling this variable?
- disable_var(var);
- } else {
- var->sharing_weight = weight;
- }
-
- check_concurrency();
-
- XBT_OUT();
-}
-
-void System::update_constraint_bound(Constraint* cnst, double bound)
-{
- modified = true;
- update_modified_set(cnst);
- cnst->bound = bound;
-}
-
-/** \brief Update the constraint set propagating recursively to other constraints so the system should not be entirely
- * computed.
- *
- * \param cnst the Constraint* affected by the change
- *
- * A recursive algorithm to optimize the system recalculation selecting only constraints that have changed. Each
- * constraint change is propagated to the list of constraints for each variable.
- */
-void System::update_modified_set_rec(Constraint* cnst)
-{
- for (Element const& elem : cnst->enabled_element_set) {
- Variable* var = elem.variable;
- for (Element const& elem2 : var->cnsts) {
- if (var->visited == visited_counter)
- break;
- if (elem2.constraint != cnst && not elem2.constraint->modified_constraint_set_hook.is_linked()) {
- modified_constraint_set.push_back(*elem2.constraint);
- update_modified_set_rec(elem2.constraint);
- }
- }
- // var will be ignored in later visits as long as sys->visited_counter does not move
- var->visited = visited_counter;
- }
-}
-
-void System::update_modified_set(Constraint* cnst)
-{
- /* nothing to do if selective update isn't active */
- if (selective_update_active && not cnst->modified_constraint_set_hook.is_linked()) {
- modified_constraint_set.push_back(*cnst);
- update_modified_set_rec(cnst);
- }
-}
-
-void System::remove_all_modified_set()
-{
- // We cleverly un-flag all variables just by incrementing visited_counter
- // In effect, the var->visited value will no more be equal to visited counter
- // To be clean, when visited counter has wrapped around, we force these var->visited values so that variables that
- // were in the modified a long long time ago are not wrongly skipped here, which would lead to very nasty bugs
- // (i.e. not readibily reproducible, and requiring a lot of run time before happening).
- if (++visited_counter == 1) {
- /* the counter wrapped around, reset each variable->visited */
- for (Variable& var : variable_set)
- var.visited = 0;
- }
- modified_constraint_set.clear();
-}
-
-/**
- * Returns resource load (in flop per second, or byte per second, or similar)
- *
- * If the resource is shared (the default case), the load is sum of resource usage made by every variables located on
- * this resource.
- *
- * If the resource is not shared (ie in FATPIPE mode), then the load is the max (not the sum) of all resource usages
- * located on this resource.
- */
-double Constraint::get_usage() const
-{
- double result = 0.0;
- if (sharing_policy) {
- for (Element const& elem : enabled_element_set)
- if (elem.consumption_weight > 0)
- result += elem.consumption_weight * elem.variable->value;
- } else {
- for (Element const& elem : enabled_element_set)
- if (elem.consumption_weight > 0)
- result = std::max(result, elem.consumption_weight * elem.variable->value);
- }
- return result;
-}
-
-int Constraint::get_variable_amount() const
-{
- return std::count_if(std::begin(enabled_element_set), std::end(enabled_element_set),
- [](const Element& elem) { return elem.consumption_weight > 0; });
-}
-}
-}
-}