D. Servicios Web Desarrollados 61
B.1. Modelo Incremental
As the name implies, the static data-flow dispatcher dispatches data-events. These data-events can either be triggered or not. But some applications might require to trigger an event several times, before the actual dispatch can be done. In this section the static data-flow dispatcher is extended with dependency counters fulfilling this need.
Figure 3.17 shows this extension using an interposed counter. Figure 3.17 (a) represents the direct triggering of a data-event and Figure 3.17 (b) shows the delayed event triggering through a dependency counter. As presented in this
E
TaskA
TaskB trigger
(a)Without Counter
Counter
E
TaskA
TaskB
(b)With Counter
Figure 3.17:Without a dependency counter, the data event can be triggered directly. By introducing a dependency counter, the trigger is delayed with respect to the counter.
Listing 3.20:DependencyCounter wrapper class
1 template <DataEventSet event>
2 struct DependencyCounter { 3 4 //... 5 6 std::atomic<std::size_t> counter_; 7 };
example, all data-events will be extended by a dependency counter. When the data-flow dispatcher dispatches an event, the dependency counter of this event will be decremented and only if the counter becomes zero, the actual event is dispatched.
The data-flow dispatcher should be highly configurable. Therefore it is required, that the dependency counters are generated automatically from the configuration of the data-flow dispatcher. Again, this is done with the help of TMP. For every data-event used in the configuration of the data-flow dispatcher a separate counter will be created. As an example the automatically generated dependency counters for the static data-flow dispatcher from Listing 3.19 would encompass counters forDataEvent1,DataEvent3 andDataEvent2.
The counters itself are encapsulated in a wrapper class calledDependencyCounter. This encapsulation is required to allow user-defined default values. The imple- mentation of theDependencyCounterclass is shown in Listing 3.20. This class uses
atomics from the standard library [68, pp. 1012] by default to allow thread safe concurrent counting.
Since the counters are generated at compile-time it becomes complicated for the user to define their default values. But for the most algorithms, it is required to set algorithm-specific initial values for different data-events. This can be done with the helper class shown in Listing 3.21. The value provided in this class will be used as an initial value for the specific data-event dependency counter. To set a default value for a data-event, this class must be specialized for this data-event.
2 struct DependencyCounterDefaults {
3 // Without specialization, all counter are set to 1
4 const static size_t value = 1;
5 };
6
7 template <>
8 struct DependencyCounterDefaults<DataEvent1> {
9 // Counter for DataEvent1 is set to 100
10 const static size_t value = 100;
11 }; BC BC BC BC BC BC BC LC LC LC TC
Figure 3.18:If a box counter (BC) becomes zero, the level counter (LC) will be decremented automatically. If the level counter becomes zero, additionally the tree counter (TC) will be decremented.
Hierarchical Counters and Data Events
Not all applications have such simple dependencies. For hierarchical methods like tree codes or the FMM it makes sense to extend the concept of data-events and counters with respect to the surrounding data structure hierarchy. For the FMM this would mean, a data-event can be triggered for a vertex in the tree, a complete level in the tree or for the entire tree. For this purpose, a set of hierarchy levels is defined (e.g. vertex, level, tree) and the event listener is extended to support these hierarchy levels.
Definition 3.9 A Hierarchical Event Listener is the combination of an event listener and a hierarchy level.
A hierarchical event listener is only registered for the data-event on the corre- sponding hierarchy level. An example of this idea for a tree-based structure is shown in Figure 3.18. This tree has three levels and seven vertices. The set of hierarchy levels encompasses vertex, level and tree. For each vertex, level and tree a data-event is defined and a dependency counter will be created. Only the data-events on the lowest level in the hierarchy can be triggered by the user. In
dispatcher task factory task execution dependency counter task creation
Figure 3.19:The flow of the dependency manager. After a task was executed, the cor- responding dependency counters are decremented. If a dependency counter becomes zero, the dispatcher will be invoked. The dispatcher will create a new task using the task factory if necessary.
this example these are data-events on the vertex level. All other data-events (level data-events and tree data-events) are derived and will be triggered internally.
The hierarchical counter work-flow is as follows: Whenever a vertex counter becomes zero, a data-event for the vertex is triggered. Additionally, the counter for the next hierarchy level is notified. For the tree example this would be the level counter. In this way, the data-event propagates upwards in the hierarchy. When all data-events of a level have been triggered, the data-event will be triggered for the level itself. This will also notify the counter for the entire tree. When all levels triggered the data-event for the level, the data-event for the entire tree will be triggered automatically.