Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
338a5ab61ea07837dbfa1723dc5f1671eb9469f0
[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 void Action::set_bound(double bound)
100 {
101   XBT_IN("(%p,%g)", this, bound);
102   if (variable_)
103     model_->get_maxmin_system()->update_variable_bound(variable_, bound);
104
105   if (model_->is_update_lazy() && get_last_update() != surf_get_clock())
106     model_->get_action_heap().remove(this);
107   XBT_OUT();
108 }
109
110 void Action::ref()
111 {
112   refcount_++;
113 }
114
115 void Action::set_max_duration(double duration)
116 {
117   max_duration_ = duration;
118   if (model_->is_update_lazy()) // remove action from the heap
119     model_->get_action_heap().remove(this);
120 }
121
122 void Action::set_sharing_penalty(double sharing_penalty)
123 {
124   XBT_IN("(%p,%g)", this, sharing_penalty);
125   sharing_penalty_ = sharing_penalty;
126   model_->get_maxmin_system()->update_variable_penalty(get_variable(), sharing_penalty);
127
128   if (model_->is_update_lazy())
129     model_->get_action_heap().remove(this);
130   XBT_OUT();
131 }
132
133 void Action::cancel()
134 {
135   set_state(Action::State::FAILED);
136   if (model_->is_update_lazy()) {
137     if (modified_set_hook_.is_linked())
138       xbt::intrusive_erase(*model_->get_modified_set(), *this);
139     model_->get_action_heap().remove(this);
140   }
141 }
142
143 bool Action::unref()
144 {
145   refcount_--;
146   if (not refcount_) {
147     delete this;
148     return true;
149   }
150   return false;
151 }
152
153 void Action::suspend()
154 {
155   XBT_IN("(%p)", this);
156   if (suspended_ != SuspendStates::SLEEPING) {
157     model_->get_maxmin_system()->update_variable_penalty(get_variable(), 0.0);
158     if (model_->is_update_lazy()) {
159       model_->get_action_heap().remove(this);
160       if (state_set_ == model_->get_started_action_set() && sharing_penalty_ > 0) {
161         // If we have a lazy model, we need to update the remaining value accordingly
162         update_remains_lazy(surf_get_clock());
163       }
164     }
165     suspended_ = SuspendStates::SUSPENDED;
166   }
167   XBT_OUT();
168 }
169
170 void Action::resume()
171 {
172   XBT_IN("(%p)", this);
173   if (suspended_ != SuspendStates::SLEEPING) {
174     model_->get_maxmin_system()->update_variable_penalty(get_variable(), get_sharing_penalty());
175     suspended_ = SuspendStates::RUNNING;
176     if (model_->is_update_lazy())
177       model_->get_action_heap().remove(this);
178   }
179   XBT_OUT();
180 }
181
182 double Action::get_remains()
183 {
184   XBT_IN("(%p)", this);
185   /* update remains before returning it */
186   if (model_->is_update_lazy()) /* update remains before return it */
187     update_remains_lazy(surf_get_clock());
188   XBT_OUT();
189   return remains_;
190 }
191
192 void Action::update_max_duration(double delta)
193 {
194   if (max_duration_ != NO_MAX_DURATION)
195     double_update(&max_duration_, delta, sg_surf_precision);
196 }
197
198 void Action::update_remains(double delta)
199 {
200   double_update(&remains_, delta, sg_maxmin_precision * sg_surf_precision);
201 }
202
203 void Action::set_last_update()
204 {
205   last_update_ = surf_get_clock();
206 }
207
208 double ActionHeap::top_date() const
209 {
210   return top().first;
211 }
212
213 void ActionHeap::insert(Action* action, double date, ActionHeap::Type type)
214 {
215   action->type_      = type;
216   action->heap_hook_ = emplace(std::make_pair(date, action));
217 }
218
219 void ActionHeap::remove(Action* action)
220 {
221   action->type_ = ActionHeap::Type::unset;
222   if (action->heap_hook_) {
223     erase(*action->heap_hook_);
224     action->heap_hook_ = boost::none;
225   }
226 }
227
228 void ActionHeap::update(Action* action, double date, ActionHeap::Type type)
229 {
230   action->type_ = type;
231   if (action->heap_hook_) {
232     heap_type::update(*action->heap_hook_, std::make_pair(date, action));
233   } else {
234     action->heap_hook_ = emplace(std::make_pair(date, action));
235   }
236 }
237
238 Action* ActionHeap::pop()
239 {
240   Action* action = top().second;
241   heap_type::pop();
242   action->heap_hook_ = boost::none;
243   return action;
244 }
245
246 } // namespace resource
247 } // namespace kernel
248 } // namespace simgrid