+ kernel::activity::ActivityImplPtr pimpl_ = nullptr;
+ Activity::State state_ = Activity::State::INITED;
+ double remains_ = 0;
+ 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_ = "";
+
+protected:
+ 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;
+
+public:
+ /*! \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); }
+
+ 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);
+ }
+
+ 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
+};