comm->add_successor(exec2);
// Add a function to be called when operations end for log purpose
- std::vector<simgrid::plugins::OperationPtr> ops{exec1, exec2, comm};
- for (auto op : ops)
- op->on_end([](simgrid::plugins::Operation* op) {
- XBT_INFO("Operation %s finished (%d)", op->get_name().c_str(), op->get_count());
- });
+ simgrid::plugins::Operation::on_end_cb([](simgrid::plugins::Operation* op) {
+ XBT_INFO("Operation %s finished (%d)", op->get_name().c_str(), op->get_count());
+ });
// Enqueue two executions for operation exec1
exec1->enqueue_execs(2);
exec2->add_successor(comm2);
// Add a function to be called when operations end for log purpose
- std::vector<simgrid::plugins::OperationPtr> v = {comm0, exec1, exec2, comm1, comm2};
- for (auto op : v)
- op->on_end([](simgrid::plugins::Operation* op) {
- XBT_INFO("Operation %s finished (%d)", op->get_name().c_str(), op->get_count());
- });
+ simgrid::plugins::Operation::on_end_cb([](simgrid::plugins::Operation* op) {
+ XBT_INFO("Operation %s finished (%d)", op->get_name().c_str(), op->get_count());
+ });
// Add a function to be called before each executions of comm0
// This function modifies the graph of operations by adding or removing
// successors to comm0
int count = 0;
- comm0->on_start([&](simgrid::plugins::Operation* op) {
+ comm0->on_this_start([&](simgrid::plugins::Operation* op) {
if (count % 2 == 0) {
comm0->set_destination(jupiter);
comm0->add_successor(exec1);
comm->add_successor(exec);
// Add a function to be called when operations end for log purpose
- std::vector<simgrid::plugins::OperationPtr> ops{exec, comm};
- for (auto op : ops)
- op->on_end([](simgrid::plugins::Operation* op) {
- XBT_INFO("Operation %s finished (%d)", op->get_name().c_str(), op->get_count());
- });
+ simgrid::plugins::Operation::on_end_cb([](simgrid::plugins::Operation* op) {
+ XBT_INFO("Operation %s finished (%d)", op->get_name().c_str(), op->get_count());
+ });
// Create the actor that will inject load during the simulation
simgrid::s4u::Actor::create("input", tremblay, variable_load, comm);
virtual ~Operation() = default;
virtual void execute() = 0;
+ static xbt::signal<void(Operation*)> on_start;
+ static xbt::signal<void(Operation*)> on_end;
+
public:
static void init();
std::string get_name();
void set_amount(double amount);
void add_successor(OperationPtr op);
void remove_successor(OperationPtr op);
- void on_start(std::function<void(Operation*)> func);
- void on_end(std::function<void(Operation*)> func);
+ void on_this_start(std::function<void(Operation*)> func);
+ void on_this_end(std::function<void(Operation*)> func);
int get_count();
+
+ /** Add a callback fired before an operation activity start.
+ * Triggered after the on_this_start function**/
+ static void on_start_cb(const std::function<void(Operation*)>& cb) { on_start.connect(cb); }
+ /** Add a callback fired after an operation activity end.
+ * Triggered after the on_this_end function, but before
+ * sending tokens to successors.**/
+ static void on_end_cb(const std::function<void(Operation*)>& cb) { on_end.connect(cb); }
};
class ExecOp : public Operation {
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(Operation, kernel, "Logging specific to the operation plugin");
namespace simgrid::plugins {
+
+xbt::signal<void(Operation*)> Operation::on_start;
+xbt::signal<void(Operation*)> Operation::on_end;
+
Operation::Operation(const std::string& name, double amount) : name_(name), amount_(amount) {}
std::string Operation::get_name()
/**
* @brief Operation routine when finishing an execution.
- * @note Set its working status as false. Add 1 to its count of finished executions.
- * Call the on_end() func. Send a token to each of its successors.
+ * @note Set its working status as false.
+ * Add 1 to its count of finished executions.
+ * Call the on_this_end func.
+ * Fire on_end callback.
+ * Send a token to each of its successors.
* Start a new execution if possible.
*/
void Operation::complete()
count_++;
});
end_func_(this);
+ Operation::on_end(this);
for (auto const& op : successors_)
op->receive(this);
if (ready_to_run())
* @brief Set a function to be called before each execution.
* @note The function is called before the underlying Activity starts.
*/
-void Operation::on_start(std::function<void(Operation*)> func)
+void Operation::on_this_start(std::function<void(Operation*)> func)
{
simgrid::kernel::actor::simcall_answered([this, func] { start_func_ = func; });
}
* @brief Set a function to be called after each execution.
* @note The function is called after the underlying Activity ends, but before sending tokens to successors.
*/
-void Operation::on_end(std::function<void(Operation*)> func)
+void Operation::on_this_end(std::function<void(Operation*)> func)
{
simgrid::kernel::actor::simcall_answered([this, func] { end_func_ = func; });
}
/**
* @brief Do one execution of the Operation.
- * @note Call the on_start() func. Set its working status as true.
+ * @note Call the on_this_start() func. Set its working status as true.
* Create and start the underlying Activity.
*/
void ExecOp::execute()
{
start_func_(this);
+ Operation::on_start(this);
simgrid::kernel::actor::simcall_answered([this] {
working_ = true;
queued_execs_ = std::max(queued_execs_ - 1, 0);
/**
* @brief Do one execution of the Operation.
- * @note Call the on_start() func. Set its working status as true.
+ * @note Call the on_this_start() func. Set its working status as true.
* Create and start the underlying Activity.
*/
void CommOp::execute()
{
start_func_(this);
+ Operation::on_start(this);
simgrid::kernel::actor::simcall_answered([this] {
working_ = true;
queued_execs_ = std::max(queued_execs_ - 1, 0);