5.4 Optimistic runtime
5.4.3 Events scheduling
The Optimistic PEV runtime implements a different, simpler, scheduling policy than the Pessimistic one. The high-level description of the scheduling approach for this runtime is depicted in Figure 5.6.
In the Optimistic runtime, both the main thread and worker threads are responsible for processing any type of event, regardless of their event target. The goal for this design is providing a fair scheduling not biased towards the main thread. As with the Pessimistic runtime, the main thread is the only thread receiving events from the global queue (generated by the I/O substrate); differently, the main thread does not use the global queue for global ordered events, meaning that calls to emit from the main thread will not cause events to be added to the global queue, but rather to one of the worker’s queues, selected randomly. Globally ordered events are considered at the same level of other event types, and are therefore processed by workers. Like with the Pessimistic runtime, chained events are assigned to a specific worker using hashing. Differently, every unordered event emission -including unordered events with a non-global target- are potentially processed in parallel by the PEV runtime, as worker threads implement work stealing. In particular, every worker has a concurrent double- ended queue used by worker threads to route chained events and to steal tasks using an approach similar to the one of the Java ForkJoin Pool [110]. Differently from
83 5.4 Optimistic runtime Global queue I/O substrate Main thread Worker thread #1 Worker thread #N emit emitChained (#1) emitUnordered emitNow emitChained (#N) Work stealing emit emitNow emitChained emitUnordered
Figure 5.6. Optimistic routing scheme.
the ForkJoin pool, however, tasks emitted by a worker to its own queue are always added on top of the queue, and therefore the worker thread always processes oldest tasks first3. Following the same approach, idle threads that attempt to steal work from a worker thread will do so by trying to steal tasks from the top of the queue. Independently of the type of event that was acquired (ordered vs. unordered) the thief thread will immediately attempt execution. In this way, also ordered event handlers will potentially run in parallel. As will be discussed in the next section, a special commit-time STM barrier will make sure that this kind of out-of-order speculation does not violate the semantics of the PEV API for ordered event emission. A summary of the Optimistic PEV runtime is presented in Table 5.2.
Shared metadata and unordered commit barriers
The Optimistic PEV runtime implemented using the TL2 algorithm uses event targets to implement event processing with the correct order (event targets rely on the structure described in Section 5.2.5). Every event instance holds a reference to its correspond- ing event target object, which is usually the object that emitted the event instance. Depending on the event emission type, the event is modified with distinct TM barriers, as follows:
• Globally unordered events are executed directly, with barriers implementing the standard TL2 algorithm. Depending on the global target, they might be assigned to any available thread, or to a subset of threads.
3Conversely, when a thread in the ForkJoinPool attempts to process tasks from its own queue, usually
84 5.4 Optimistic runtime
Main thread Worker threads
emit In Received from Global queue from Main thread or work stealing
Out Sent to random worker To local queue (might be stolen). Commit-time bar- rier enforces ordering.
emitChained In Cannot receive From local queue (emitted by the worker itself) or work stealing
Out To hashed worker To local queue (might be stolen). Commit-time bar- rier enforces ordering.
emitNow In Cannot receive From local queue (emitted by the worker itself) or work stealing
Out To random worker To local queue (might be stolen)
emitUnordered In Cannot receive From local queue (emitted by the worker itself) or work stealing
Out To random worker To local queue (might be stolen)
Barriers Same for main and workers (STM)
Out-Of-order speculation Supported, for every event type includingemit
Irrevocability Via global lock acquisition
Table 5.2. Optimistic speculation summary.
• Other types of events require different runtime barriers that make use of a unique sequence id. The id is assigned to every event instance, and is compared against thenextCommittingEventof the corresponding event target to impose the cor- rect event execution order for multiple event handlers. Event IDs are guaranteed to be unique on a per-target basis.
Unordered events use standard STM barriers, and are executed by some worker threads as soon as possible. Their execution loop is presented in Figure 5.7, and cor- responds to a common loop for software transactions, extended with events buffering and delayed emission. As common with STM-based runtimes, the software transaction runs in an infinite loop that will exit only when the transaction will have successfully committed. While executing, no other thread will be able to see the modifications
85 5.4 Optimistic runtime
1 // The infinite event loop for this worker thread
2 while (true) {
3 boolean commit = false;
4 // Get the event from the queue
5 Event event = localQueue.pop();
6 do {
7 try {
8 // Try to run the event handler in a software transaction
9 TxStart(event); 10 commit = TxCommit(event); 11 } catch (TxAbortAndRestartException e) { 12 // If aborted, restart 13 event.localEmitBuffer.clear(); 14 continue; 15 } 16 } while (!commit); 17 for(Event e : event.localEmitBuffer) {
18 // send the event to the correct queue according to scheduling rules
19 schedule(e);
20 }
21 }
Figure 5.7. Event handlers execution loop using an STM-based runtime.
done by the transaction (as it is running in isolation). In case of early abort or commit- time abort (e.g., because of conflicts with other concurrent transactions) an exception is thrown that will force the transaction to invalidate its transactional logs, and the transaction will be re-started. TheworkerCommitmethod for unordered events simply compares the transaction-local logs against the global metadata in order to validate the transaction, and in case of successful validation publishes the values as computed by the transaction.