Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Move the files related to the platform parsing to kernel/xml
[simgrid.git] / src / kernel / resource / Action.cpp
1 /* Copyright (c) 2004-2023. The SimGrid Team. All rights reserved.          */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include "simgrid/kernel/resource/Action.hpp"
7 #include "simgrid/kernel/resource/Model.hpp"
8 #include "src/kernel/EngineImpl.hpp"
9 #include "src/kernel/lmm/maxmin.hpp"
10
11 XBT_LOG_NEW_CATEGORY(kernel, "SimGrid internals");
12 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ker_resource, kernel, "Resources, modeling the platform performance");
13
14 namespace simgrid::kernel::resource {
15
16 Action::Action(Model* model, double cost, bool failed) : Action(model, cost, failed, nullptr) {}
17
18 Action::Action(Model* model, double cost, bool failed, lmm::Variable* var)
19     : remains_(cost), start_time_(EngineImpl::get_clock()), cost_(cost), model_(model), variable_(var)
20 {
21   if (failed)
22     state_set_ = model_->get_failed_action_set();
23   else
24     state_set_ = model_->get_started_action_set();
25
26   state_set_->push_back(*this);
27 }
28
29 Action::~Action()
30 {
31   if (state_set_hook_.is_linked())
32     xbt::intrusive_erase(*state_set_, *this);
33   if (get_variable())
34     model_->get_maxmin_system()->variable_free(get_variable());
35
36   /* remove from heap on need (ie, if selective update) */
37   model_->get_action_heap().remove(this);
38   if (modified_set_hook_.is_linked())
39     xbt::intrusive_erase(*model_->get_modified_set(), *this);
40 }
41
42 void Action::finish(Action::State state)
43 {
44   finish_time_ = EngineImpl::get_clock();
45   set_remains(0);
46   set_state(state);
47 }
48
49 Action::State Action::get_state() const
50 {
51   if (state_set_ == model_->get_inited_action_set())
52     return Action::State::INITED;
53   if (state_set_ == model_->get_started_action_set())
54     return Action::State::STARTED;
55   if (state_set_ == model_->get_failed_action_set())
56     return Action::State::FAILED;
57   if (state_set_ == model_->get_finished_action_set())
58     return Action::State::FINISHED;
59   if (state_set_ == model_->get_ignored_action_set())
60     return Action::State::IGNORED;
61   THROW_IMPOSSIBLE;
62 }
63
64 void Action::set_state(Action::State state)
65 {
66   xbt::intrusive_erase(*state_set_, *this);
67   switch (state) {
68     case Action::State::INITED:
69       state_set_ = model_->get_inited_action_set();
70       break;
71     case Action::State::STARTED:
72       state_set_ = model_->get_started_action_set();
73       break;
74     case Action::State::FAILED:
75       state_set_ = model_->get_failed_action_set();
76       break;
77     case Action::State::FINISHED:
78       state_set_ = model_->get_finished_action_set();
79       break;
80     case Action::State::IGNORED:
81       state_set_ = model_->get_ignored_action_set();
82       break;
83     default:
84       state_set_ = nullptr;
85       break;
86   }
87   if (state_set_)
88     state_set_->push_back(*this);
89 }
90
91 double Action::get_bound() const
92 {
93   return variable_ ? variable_->get_bound() : 0;
94 }
95
96 double Action::get_rate() const
97 {
98   return variable_ ? variable_->get_value() * factor_ : 0;
99 }
100
101 void Action::set_bound(double bound)
102 {
103   XBT_IN("(%p,%g)", this, bound);
104   if (variable_)
105     model_->get_maxmin_system()->update_variable_bound(variable_, bound);
106
107   if (model_->is_update_lazy() && get_last_update() != EngineImpl::get_clock())
108     model_->get_action_heap().remove(this);
109   XBT_OUT();
110 }
111
112 void Action::ref()
113 {
114   refcount_++;
115 }
116
117 void Action::set_max_duration(double duration)
118 {
119   max_duration_ = duration;
120   if (model_->is_update_lazy()) // remove action from the heap
121     model_->get_action_heap().remove(this);
122 }
123
124 void Action::set_sharing_penalty(double sharing_penalty)
125 {
126   XBT_IN("(%p,%g)", this, sharing_penalty);
127   sharing_penalty_ = sharing_penalty;
128   model_->get_maxmin_system()->update_variable_penalty(get_variable(), sharing_penalty);
129   if (model_->is_update_lazy())
130     model_->get_action_heap().remove(this);
131   XBT_OUT();
132 }
133
134 void Action::cancel()
135 {
136   set_state(Action::State::FAILED);
137   if (model_->is_update_lazy()) {
138     if (modified_set_hook_.is_linked())
139       xbt::intrusive_erase(*model_->get_modified_set(), *this);
140     model_->get_action_heap().remove(this);
141   }
142 }
143
144 bool Action::unref()
145 {
146   refcount_--;
147   if (not refcount_) {
148     delete this;
149     return true;
150   }
151   return false;
152 }
153
154 void Action::suspend()
155 {
156   XBT_IN("(%p)", this);
157   if (suspended_ != SuspendStates::SLEEPING) {
158     model_->get_maxmin_system()->update_variable_penalty(get_variable(), 0.0);
159     if (model_->is_update_lazy()) {
160       model_->get_action_heap().remove(this);
161       if (state_set_ == model_->get_started_action_set() && sharing_penalty_ > 0) {
162         // If we have a lazy model, we need to update the remaining value accordingly
163         update_remains_lazy(EngineImpl::get_clock());
164       }
165     }
166     suspended_ = SuspendStates::SUSPENDED;
167   }
168   XBT_OUT();
169 }
170
171 void Action::resume()
172 {
173   XBT_IN("(%p)", this);
174   if (suspended_ != SuspendStates::SLEEPING) {
175     model_->get_maxmin_system()->update_variable_penalty(get_variable(), get_sharing_penalty());
176     suspended_ = SuspendStates::RUNNING;
177     if (model_->is_update_lazy())
178       model_->get_action_heap().remove(this);
179   }
180   XBT_OUT();
181 }
182
183 double Action::get_remains()
184 {
185   XBT_IN("(%p)", this);
186   /* update remains before returning it */
187   if (model_->is_update_lazy()) /* update remains before return it */
188     update_remains_lazy(EngineImpl::get_clock());
189   XBT_OUT();
190   return remains_;
191 }
192
193 void Action::update_max_duration(double delta)
194 {
195   if (max_duration_ != NO_MAX_DURATION)
196     double_update(&max_duration_, delta, sg_precision_timing);
197 }
198
199 void Action::update_remains(double delta)
200 {
201   double_update(&remains_, delta, sg_precision_workamount * sg_precision_timing);
202 }
203
204 void Action::set_last_update()
205 {
206   last_update_ = EngineImpl::get_clock();
207 }
208
209 double ActionHeap::top_date() const
210 {
211   return top().first;
212 }
213
214 void ActionHeap::insert(Action* action, double date, ActionHeap::Type type)
215 {
216   action->type_      = type;
217   action->heap_hook_ = emplace(std::make_pair(date, action));
218 }
219
220 void ActionHeap::remove(Action* action)
221 {
222   action->type_ = ActionHeap::Type::unset;
223   if (action->heap_hook_) {
224     erase(*action->heap_hook_);
225     action->heap_hook_ = boost::none;
226   }
227 }
228
229 void ActionHeap::update(Action* action, double date, ActionHeap::Type type)
230 {
231   action->type_ = type;
232   if (action->heap_hook_) {
233     heap_type::update(*action->heap_hook_, std::make_pair(date, action));
234   } else {
235     action->heap_hook_ = emplace(std::make_pair(date, action));
236   }
237 }
238
239 Action* ActionHeap::pop()
240 {
241   Action* action = top().second;
242   heap_type::pop();
243   action->heap_hook_ = boost::none;
244   return action;
245 }
246
247 } // namespace simgrid::kernel::resource