Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Document ActivitySet
[simgrid.git] / include / simgrid / s4u / ActivitySet.hpp
1 /* Copyright (c) 2006-2023. 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 #ifndef SIMGRID_S4U_ACTIVITYSET_HPP
7 #define SIMGRID_S4U_ACTIVITYSET_HPP
8
9 #include <simgrid/forward.h>
10 #include <simgrid/s4u/Activity.hpp>
11
12 #include <vector>
13
14 namespace simgrid {
15
16 extern template class XBT_PUBLIC xbt::Extendable<s4u::ActivitySet>;
17
18 namespace s4u {
19 /** @brief ActivitiesSet
20  *
21  * This class is a container of activities, allowing to wait for the completion of any or all activities in the set.
22  * This is somehow similar to the select(2) system call under UNIX, allowing you to wait for the next event about these
23  * activities.
24  */
25 class XBT_PUBLIC ActivitySet : public xbt::Extendable<ActivitySet> {
26   std::atomic_int_fast32_t refcount_{1};
27   std::vector<ActivityPtr> activities_; // Use vectors, not sets for better reproductibility accross architectures
28   std::vector<ActivityPtr> failed_activities_;
29
30   void handle_failed_activities();
31
32 public:
33   ActivitySet()  = default;
34   ActivitySet(const std::vector<ActivityPtr> init) : activities_(init) {}
35   ~ActivitySet() = default;
36
37   /** Add an activity to the set */
38   void push(ActivityPtr a) { activities_.push_back(a); }
39   /** Remove that activity from the set (no-op if the activity is not in the set) */
40   void erase(ActivityPtr a);
41
42   /** Get the amount of activities in the set. Failed activities (if any) are not counted */
43   int size() { return activities_.size(); }
44   /** Return whether the set is empty. Failed activities (if any) are not counted */
45   int empty() { return activities_.empty(); }
46
47   /** Wait for the completion of all activities in the set, but not longer than the provided timeout
48    *
49    * On timeout, an exception is raised.
50    *
51    * In any case, the completed activities remain in the set. Use test_any() to retrieve them.
52    */
53   void wait_all_for(double timeout);
54   /** Wait for the completion of all activities in the set. The set is NOT emptied afterward. */
55   void wait_all() { wait_all_for(-1); }
56   /** Returns the first terminated activity if any, or ActivityPtr(nullptr) if no activity is terminated */
57   ActivityPtr test_any();
58
59   /** Wait for the completion of one activity from the set, but not longer than the provided timeout.
60    *
61    *  See wait_any() for details.
62    *
63    * @return the first terminated activity, which is automatically removed from the set.
64    */
65
66   ActivityPtr wait_any_for(double timeout);
67   /** Wait for the completion of one activity from the set.
68    *
69    * If an activity fails during that time, an exception is raised, and the failed exception is marked as failed in the
70    * set. Use get_failed_activity() to retrieve it.
71    *
72    * If more than one activity failed, the other ones are also removed from the set. Use get_failed_activity() several
73    * time to retrieve them all.
74    *
75    * @return the first terminated activity, which is automatically removed from the set. If more than one activity
76    * terminated at the same timestamp, then the other ones are still in the set. Use either test_any() or wait_any() to
77    * retrieve the other ones.
78    */
79   ActivityPtr wait_any() { return wait_any_for(-1); }
80
81   /** Return one of the failed activity of the set that was revealed during the previous wait operation, or
82    * ActivityPtr() if no failed activity exist in the set. */
83   ActivityPtr get_failed_activity();
84   /** Return whether the set contains any failed activity. */
85   bool has_failed_activities() { return not failed_activities_.empty(); }
86
87   // boost::intrusive_ptr<ActivitySet> support:
88   friend void intrusive_ptr_add_ref(ActivitySet* as)
89   {
90     XBT_ATTRIB_UNUSED auto previous = as->refcount_.fetch_add(1);
91     xbt_assert(previous != 0);
92   }
93
94   friend void intrusive_ptr_release(ActivitySet* as)
95   {
96     if (as->refcount_.fetch_sub(1) == 1)
97       delete as;
98   }
99 };
100
101 } // namespace s4u
102 } // namespace simgrid
103
104 #endif