فهرست منبع

doc: graph (close #957)

Michele Caini 3 سال پیش
والد
کامیت
c2f6ca43f1
1فایلهای تغییر یافته به همراه74 افزوده شده و 0 حذف شده
  1. 74 0
      docs/md/graph.md

+ 74 - 0
docs/md/graph.md

@@ -210,6 +210,80 @@ tools offered by the library while leaving room for maximum flexibility.
 Finally, both the `ro` and` rw` functions also offer an overload that accepts a
 pair of iterators, so that one can pass a range of resources in one go.
 
+### Rebinding
+
+The `flow` class is resource based rather than task based. This means that graph
+generation is driven by resources and not by the order of _appearance_ of tasks
+during flow definition.<br/>
+Although this concept is particularly important, it's almost irrelevant for the
+vast majority of cases. However, it becomes relevant when _rebinding_ resources
+or tasks.
+
+In fact, nothing prevents rebinding elements to a flow.<br/>
+However, the behavior changes slightly from case to case and has some nuances
+that it's worth knowing about.
+
+Directly rebinding a resource without the task being replaced trivially results
+in the task's access mode for that resource being updated:
+
+```cpp
+builder.bind("task"_hs).rw("resource"_hs).ro("resource"_hs)
+```
+
+In this case, the resource is accessed in read-only mode, regardless of the
+first call to `rw`.<br/>
+Behind the scenes, the call doesn't actually _replace_ the previous one but is
+queued after it instead, overwriting it when generating the graph. Thus, a large
+number of resource rebindings may even impact processing times (very difficult
+to observe but theoretically possible).
+
+Rebinding resources and also combining it with changes to tasks has far more
+implications instead.<br/>
+As mentioned, graph generation takes place starting from resources and not from
+tasks. Therefore, the result may not be as expected:
+
+```cpp
+builder
+    .bind("task_1"_hs)
+        .ro("resource"_hs)
+    .bind("task_2"_hs)
+        .ro("resource"_hs)
+    .bind("task_1"_hs)
+        .rw("resource"_hs);
+```
+
+What happens here is that the resource first _sees_ a read-only access request
+from the first task, then a read-write request from the second task and finally
+a new read-only request from the first task.<br/>
+Although this definition would probably be counted as an error, the resulting
+graph may be unexpected. This in fact consists of a single edge outgoing from
+the second task and directed to the first task.<br/>
+To intuitively understand what happens, it's enough to think of the fact that a
+task never has an edge pointing to itself.
+
+While not obvious, this approach has its pros and cons like any other solution.
+For example, creating loops is actually simple in the context of resource-based
+graph generations:
+
+```cpp
+builder
+    .bind("task_1"_hs)
+        .rw("resource"_hs)
+    .bind("task_2"_hs)
+        .rw("resource"_hs)
+    .bind("task_1"_hs)
+        .rw("resource"_hs);
+```
+
+As expected, this definition leads to the creation of two edges that define a
+loop between the two tasks.
+
+As a general rule, rebinding resources and tasks is highly discouraged because
+it could lead to subtle bugs if users don't know what they're doing.<br/>
+However, once the mechanisms of resource-based graph generation are understood,
+it can offer to the expert user a flexibility and a range of possibilities
+otherwise inaccessible.
+
 ## Fake resources and order of execution
 
 The flow builder doesn't offer the ability to specify when a task should execute