Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
5f1d222747cf8daacedb3eb409ed55c159b5bb6f
[simgrid.git] / src / s4u / s4u_Exec.cpp
1 /* Copyright (c) 2006-2018. 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/s4u/Actor.hpp"
7 #include "simgrid/s4u/Exec.hpp"
8 #include "src/kernel/activity/ExecImpl.hpp"
9 #include "xbt/log.h"
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(s4u_exec, s4u_activity, "S4U asynchronous executions");
12
13 namespace simgrid {
14 namespace s4u {
15 simgrid::xbt::signal<void(simgrid::s4u::ActorPtr)> s4u::Exec::on_start;
16 simgrid::xbt::signal<void(simgrid::s4u::ActorPtr)> s4u::Exec::on_completion;
17
18 Activity* Exec::start()
19 {
20   pimpl_ = simcall_execution_start(name_, tracing_category_, flops_amount_, 1. / priority_, bound_, host_);
21   state_ = State::STARTED;
22   on_start(Actor::self());
23   return this;
24 }
25
26 Activity* Exec::cancel()
27 {
28   simgrid::simix::simcall([this] { dynamic_cast<kernel::activity::ExecImpl*>(pimpl_.get())->cancel(); });
29   state_ = State::CANCELED;
30   return this;
31 }
32
33 Activity* Exec::wait()
34 {
35   simcall_execution_wait(pimpl_);
36   state_ = State::FINISHED;
37   on_completion(Actor::self());
38   return this;
39 }
40
41 Activity* Exec::wait(double timeout)
42 {
43   THROW_UNIMPLEMENTED;
44   return this;
45 }
46
47 /** @brief Returns whether the state of the exec is finished */
48 bool Exec::test()
49 {
50   xbt_assert(state_ == State::INITED || state_ == State::STARTED || state_ == State::FINISHED);
51
52   if (state_ == State::FINISHED)
53     return true;
54
55   if (state_ == State::INITED)
56     this->start();
57
58   if (simcall_execution_test(pimpl_)) {
59     state_ = State::FINISHED;
60     return true;
61   }
62
63   return false;
64 }
65
66 /** @brief  Change the execution priority, don't you think?
67  *
68  * An execution with twice the priority will get twice the amount of flops when the resource is shared.
69  * The default priority is 1.
70  *
71  * Currently, this cannot be changed once the exec started. */
72 ExecPtr Exec::set_priority(double priority)
73 {
74   xbt_assert(state_ == State::INITED, "Cannot change the priority of an exec after its start");
75   priority_ = priority;
76   return this;
77 }
78
79 /** @brief change the execution bound, ie the maximal amount of flops per second that it may consume, regardless of what
80  * the host may deliver
81  *
82  * Currently, this cannot be changed once the exec started. */
83 ExecPtr Exec::set_bound(double bound)
84 {
85   xbt_assert(state_ == State::INITED, "Cannot change the bound of an exec after its start");
86   bound_ = bound;
87   return this;
88 }
89
90 /** @brief Change the host on which this activity takes place.
91  *
92  * The activity cannot be terminated already (but it may be started). */
93 ExecPtr Exec::set_host(Host* host)
94 {
95   xbt_assert(state_ == State::INITED || state_ == State::STARTED,
96              "Cannot change the host of an exec once it's done (state: %d)", (int)state_);
97   if (state_ == State::STARTED)
98     boost::static_pointer_cast<simgrid::kernel::activity::ExecImpl>(pimpl_)->migrate(host);
99   host_ = host;
100   return this;
101 }
102
103 ExecPtr Exec::set_name(std::string name)
104 {
105   xbt_assert(state_ == State::INITED, "Cannot change the name of an exec after its start");
106   name_ = name;
107   return this;
108 }
109
110 ExecPtr Exec::set_tracing_category(std::string category)
111 {
112   xbt_assert(state_ == State::INITED, "Cannot change the tracing category of an exec after its start");
113   tracing_category_ = category;
114   return this;
115 }
116
117 /** @brief Retrieve the host on which this activity takes place. */
118 Host* Exec::get_host()
119 {
120   return host_;
121 }
122
123 /** @brief Returns the amount of flops that remain to be done */
124 double Exec::get_remaining()
125 {
126   return simgrid::simix::simcall(
127       [this]() { return boost::static_pointer_cast<simgrid::kernel::activity::ExecImpl>(pimpl_)->get_remaining(); });
128 }
129
130 /** @brief Returns the ratio of elements that are still to do
131  *
132  * The returned value is between 0 (completely done) and 1 (nothing done yet).
133  */
134 double Exec::get_remaining_ratio()
135 {
136   return simgrid::simix::simcall([this]() {
137     return boost::static_pointer_cast<simgrid::kernel::activity::ExecImpl>(pimpl_)->get_remaining_ratio();
138   });
139 }
140
141 void intrusive_ptr_release(simgrid::s4u::Exec* e)
142 {
143   if (e->refcount_.fetch_sub(1, std::memory_order_release) == 1) {
144     std::atomic_thread_fence(std::memory_order_acquire);
145     delete e;
146   }
147 }
148
149 void intrusive_ptr_add_ref(simgrid::s4u::Exec* e)
150 {
151   e->refcount_.fetch_add(1, std::memory_order_relaxed);
152 }
153 } // namespace s4u
154 } // namespace simgrid