+ bool suspended_ = false;
+ bool marked_ = false;
+ std::vector<ActivityPtr> successors_;
+ std::set<ActivityPtr> dependencies_;
+ std::atomic_int_fast32_t refcount_{0};
+};
+
+template <class AnyActivity> class Activity_T : public Activity {
+ std::string name_ = "unnamed";
+ std::string tracing_category_ = "";
+
+ inline static xbt::signal<void(AnyActivity const&)> on_start;
+ xbt::signal<void(AnyActivity const&)> on_this_start;
+ inline static xbt::signal<void(AnyActivity const&)> on_completion;
+ xbt::signal<void(AnyActivity const&)> on_this_completion;
+ inline static xbt::signal<void(AnyActivity const&)> on_suspend;
+ xbt::signal<void(AnyActivity const&)> on_this_suspend;
+ inline static xbt::signal<void(AnyActivity const&)> on_resume;
+ xbt::signal<void(AnyActivity const&)> on_this_resume;
+ inline static xbt::signal<void(AnyActivity&)> on_veto;
+ xbt::signal<void(AnyActivity&)> on_this_veto;
+
+protected:
+ void fire_on_start() const override { on_start(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_this_start() const override { on_this_start(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_completion() const override { on_completion(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_this_completion() const override { on_this_completion(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_suspend() const override { on_suspend(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_this_suspend() const override { on_this_suspend(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_resume() const override { on_resume(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_this_resume() const override { on_this_resume(static_cast<const AnyActivity&>(*this)); }
+ void fire_on_veto() override { on_veto(static_cast<AnyActivity&>(*this)); }
+ void fire_on_this_veto() override { on_this_veto(static_cast<AnyActivity&>(*this)); }
+
+public:
+ /*! \static Add a callback fired when any activity starts (no veto) */
+ static void on_start_cb(const std::function<void(AnyActivity const&)>& cb) { on_start.connect(cb); }
+ /*! Add a callback fired when this specific activity starts (no veto) */
+ void on_this_start_cb(const std::function<void(AnyActivity const&)>& cb) { on_this_start.connect(cb); }
+ /*! \static Add a callback fired when any activity completes (either normally, cancelled or failed) */
+ static void on_completion_cb(const std::function<void(AnyActivity const&)>& cb) { on_completion.connect(cb); }
+ /*! Add a callback fired when this specific activity completes (either normally, cancelled or failed) */
+ void on_this_completion_cb(const std::function<void(AnyActivity const&)>& cb) { on_this_completion.connect(cb); }
+ /*! \static Add a callback fired when any activity is suspended */
+ static void on_suspend_cb(const std::function<void(AnyActivity const&)>& cb) { on_suspend.connect(cb); }
+ /*! Add a callback fired when this specific activity is suspended */
+ void on_this_suspend_cb(const std::function<void(AnyActivity const&)>& cb) { on_this_suspend.connect(cb); }
+ /*! \static Add a callback fired when any activity is resumed after being suspended */
+ static void on_resume_cb(const std::function<void(AnyActivity const&)>& cb) { on_resume.connect(cb); }
+ /*! Add a callback fired when this specific activity is resumed after being suspended */
+ void on_this_resume_cb(const std::function<void(AnyActivity const&)>& cb) { on_this_resume.connect(cb); }
+ /*! \static Add a callback fired each time that any activity fails to start because of a veto (e.g., unsolved
+ * dependency or no resource assigned) */
+ static void on_veto_cb(const std::function<void(AnyActivity&)>& cb) { on_veto.connect(cb); }
+ /*! Add a callback fired each time that this specific activity fails to start because of a veto (e.g., unsolved
+ * dependency or no resource assigned) */
+ void on_this_veto_cb(const std::function<void(AnyActivity&)>& cb) { on_this_veto.connect(cb); }
+
+#ifndef DOXYGEN
+ XBT_ATTRIB_DEPRECATED_v338("Please use on_suspend_cb() instead") static void on_suspended_cb(const std::function<void(Activity const&)>& cb) { on_suspend.connect(cb); }
+ XBT_ATTRIB_DEPRECATED_v338("Please use on_resume_cb() instead") static void on_resumed_cb(const std::function<void(Activity const&)>& cb) { on_resume.connect(cb); }
+
+ XBT_ATTRIB_DEPRECATED_v339("Please use ActivitySet instead") static ssize_t wait_any(const std::vector<ActivityPtr>& activities) { return deprecated_wait_any_for(activities, -1); }
+ XBT_ATTRIB_DEPRECATED_v339("Please use ActivitySet instead") static ssize_t wait_any_for(const std::vector<ActivityPtr>& activities, double timeout) { return deprecated_wait_any_for(activities, timeout); }
+#endif
+
+ AnyActivity* add_successor(ActivityPtr a)
+ {
+ Activity::add_successor(a);
+ return static_cast<AnyActivity*>(this);
+ }
+ AnyActivity* remove_successor(ActivityPtr a)
+ {
+ Activity::remove_successor(a);
+ return static_cast<AnyActivity*>(this);
+ }
+ AnyActivity* set_name(std::string_view name)
+ {
+ name_ = name;
+ return static_cast<AnyActivity*>(this);
+ }
+ const std::string& get_name() const override { return name_; }
+ const char* get_cname() const override { return name_.c_str(); }
+
+ AnyActivity* set_tracing_category(std::string_view category)
+ {
+ xbt_assert(get_state() == State::INITED || get_state() == State::STARTING,
+ "Cannot change the tracing category of an activity after its start");
+ tracing_category_ = category;
+ return static_cast<AnyActivity*>(this);
+ }
+ const std::string& get_tracing_category() const { return tracing_category_; }
+
+ AnyActivity* start()
+ {
+ Activity::start();
+ return static_cast<AnyActivity*>(this);
+ }
+
+ AnyActivity* cancel() { return static_cast<AnyActivity*>(Activity::cancel()); }
+ AnyActivity* wait() { return wait_for(-1.0); }
+ virtual AnyActivity* wait_for(double timeout) {
+ return static_cast<AnyActivity*>(Activity::wait_for(timeout));
+ }
+
+#ifndef DOXYGEN
+ /* The refcounting is done in the ancestor class, Activity, but we want each of the classes benefiting of the CRTP
+ * (Exec, Comm, etc) to have smart pointers too, so we define these methods here, that forward the ptr_release and
+ * add_ref to the Activity class. Hopefully, the "inline" helps to not hinder the perf here.
+ */
+ friend void inline intrusive_ptr_release(AnyActivity* a) { intrusive_ptr_release(static_cast<Activity*>(a)); }
+ friend void inline intrusive_ptr_add_ref(AnyActivity* a) { intrusive_ptr_add_ref(static_cast<Activity*>(a)); }
+#endif