Logo AND Algorithmique Numérique Distribuée

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