+void Task::dependency_add(Task* task)
+{
+ if (this == task)
+ throw std::invalid_argument(
+ simgrid::xbt::string_printf("Cannot add a dependency between task '%s' and itself", get_cname()));
+
+ if (state_ == SD_DONE || state_ == SD_FAILED)
+ throw std::invalid_argument(simgrid::xbt::string_printf(
+ "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED, SD_RUNNABLE, or SD_RUNNING", get_cname()));
+
+ if (task->get_state() == SD_DONE || task->get_state() == SD_FAILED || task->get_state() == SD_RUNNING)
+ throw std::invalid_argument(simgrid::xbt::string_printf(
+ "Task '%s' must be SD_NOT_SCHEDULED, SD_SCHEDULABLE, SD_SCHEDULED, or SD_RUNNABLE", task->get_cname()));
+
+ if (dependency_exist(task))
+ throw std::invalid_argument(simgrid::xbt::string_printf(
+ "A dependency already exists between task '%s' and task '%s'", get_cname(), task->get_cname()));
+
+ successors_.push_back(task);
+ task->dependencies_.insert({this});
+
+ /* if 'task' was runnable, it goes back to the SD_SCHEDULED state because of the new dependency*/
+ if (task->get_state() == SD_RUNNABLE) {
+ XBT_DEBUG("SD_task_dependency_add: %s was runnable and becomes scheduled!", task->get_cname());
+ task->set_state(SD_SCHEDULED);
+ }
+}
+
+bool Task::dependency_exist(Task* task) const
+{
+ return (std::find(successors_.begin(), successors_.end(), task) != successors_.end() ||
+ dependencies_.find(task) != dependencies_.end());
+}
+
+void Task::dependency_remove(Task* task)
+{
+ if (this == task)
+ throw std::invalid_argument("Cannot ask to remove itself from successors");
+
+ auto p = std::find(successors_.begin(), successors_.end(), task);
+ if (p != successors_.end()) {
+ successors_.erase(p);
+ task->dependencies_.erase({this});
+ } else
+ throw std::invalid_argument(simgrid::xbt::string_printf(
+ "No dependency found between task '%s' and '%s': task '%s' is not a successor of task '%s'", get_cname(),
+ task->get_cname(), task->get_cname(), get_cname()));
+
+ /* if 'task' was scheduled and dependencies are satisfied, we can make it runnable */
+ if (task->has_unsolved_dependencies() == 0 && task->get_state() == SD_SCHEDULED)
+ task->set_state(SD_RUNNABLE);
+}
+
+std::set<Task*> Task::get_predecessors() const