Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update copyright lines for 2022.
[simgrid.git] / src / kernel / resource / Action.cpp
1 /* Copyright (c) 2004-2022. 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 #include "src/surf/surf_interface.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_(EngineImpl::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_ = EngineImpl::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() != EngineImpl::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   if (model_->is_update_lazy())
133     model_->get_action_heap().remove(this);
134   XBT_OUT();
135 }
136
137 void Action::cancel()
138 {
139   set_state(Action::State::FAILED);
140   if (model_->is_update_lazy()) {
141     if (modified_set_hook_.is_linked())
142       xbt::intrusive_erase(*model_->get_modified_set(), *this);
143     model_->get_action_heap().remove(this);
144   }
145 }
146
147 bool Action::unref()
148 {
149   refcount_--;
150   if (not refcount_) {
151     delete this;
152     return true;
153   }
154   return false;
155 }
156
157 void Action::suspend()
158 {
159   XBT_IN("(%p)", this);
160   if (suspended_ != SuspendStates::SLEEPING) {
161     model_->get_maxmin_system()->update_variable_penalty(get_variable(), 0.0);
162     if (model_->is_update_lazy()) {
163       model_->get_action_heap().remove(this);
164       if (state_set_ == model_->get_started_action_set() && sharing_penalty_ > 0) {
165         // If we have a lazy model, we need to update the remaining value accordingly
166         update_remains_lazy(EngineImpl::get_clock());
167       }
168     }
169     suspended_ = SuspendStates::SUSPENDED;
170   }
171   XBT_OUT();
172 }
173
174 void Action::resume()
175 {
176   XBT_IN("(%p)", this);
177   if (suspended_ != SuspendStates::SLEEPING) {
178     model_->get_maxmin_system()->update_variable_penalty(get_variable(), get_sharing_penalty());
179     suspended_ = SuspendStates::RUNNING;
180     if (model_->is_update_lazy())
181       model_->get_action_heap().remove(this);
182   }
183   XBT_OUT();
184 }
185
186 double Action::get_remains()
187 {
188   XBT_IN("(%p)", this);
189   /* update remains before returning it */
190   if (model_->is_update_lazy()) /* update remains before return it */
191     update_remains_lazy(EngineImpl::get_clock());
192   XBT_OUT();
193   return remains_;
194 }
195
196 void Action::update_max_duration(double delta)
197 {
198   if (max_duration_ != NO_MAX_DURATION)
199     double_update(&max_duration_, delta, sg_surf_precision);
200 }
201
202 void Action::update_remains(double delta)
203 {
204   double_update(&remains_, delta, sg_maxmin_precision * sg_surf_precision);
205 }
206
207 void Action::set_last_update()
208 {
209   last_update_ = EngineImpl::get_clock();
210 }
211
212 double ActionHeap::top_date() const
213 {
214   return top().first;
215 }
216
217 void ActionHeap::insert(Action* action, double date, ActionHeap::Type type)
218 {
219   action->type_      = type;
220   action->heap_hook_ = emplace(std::make_pair(date, action));
221 }
222
223 void ActionHeap::remove(Action* action)
224 {
225   action->type_ = ActionHeap::Type::unset;
226   if (action->heap_hook_) {
227     erase(*action->heap_hook_);
228     action->heap_hook_ = boost::none;
229   }
230 }
231
232 void ActionHeap::update(Action* action, double date, ActionHeap::Type type)
233 {
234   action->type_ = type;
235   if (action->heap_hook_) {
236     heap_type::update(*action->heap_hook_, std::make_pair(date, action));
237   } else {
238     action->heap_hook_ = emplace(std::make_pair(date, action));
239   }
240 }
241
242 Action* ActionHeap::pop()
243 {
244   Action* action = top().second;
245   heap_type::pop();
246   action->heap_hook_ = boost::none;
247   return action;
248 }
249
250 } // namespace resource
251 } // namespace kernel
252 } // namespace simgrid