Multithreading


Redesign DPP Solution: HSMs

  • Philosopher HSM
    1. States: thinking, hungry, eating
    2. Transitions to hungry and thinking triggered by TIMEOUT events
    3. Transition to hungry waits for EAT event
    4. Publishes HUNGRY(n) event on entry to hungry state [n = philosopher's number]
    5. Publishes DONE(n) event on exit from eating state
  • Table HSM
    1. Extended state variables myForks[] and myPhilophers[]
    2. On HUNGRY(n) event, publishes EAT(n) event when forks are available
    DPP Statecharts


Redesign DPP Solution: Sequence Diagram

  • DPP Sequence Diagram
    Fig 7.4


Redesign DPP Solution: Active Objects

  • Table and Philosopher (derived) QActive objects
  • QActive class inherits from QHsm
  • QActive class adds resource management and OS interaction
    • Event queue
    • Timer
    • Threads (one for each active object)
    Fig 7.5


The Relationships among RTOS, QF, and the Application

  • QF deals with RTOS
  • QF defines QHsm and and QActive
  • QF provides QTimer
  • QF manages event resources and dispatcher
  • Application deals only with QF
    QF Package Diagram


The Quantum Framework

  • Errors and Exceptions
    1. Errors: Detect w. DBC, then correct
    2. Exceptions: State-based handling
  • Memory Management
    1. Default heap: many problems
    2. Size-specific pools of footprints: much more error-free, dependable
    3. "Dynamic" memory needed for:
      1. Event pools (one for each event size)
      2. Event queues (queue of pointers to events)
      3. Runtime stacks (one for each active object/thread)
  • Mutual Exclusion and Blocking
    1. QF implementation uses only deterministic mutual exclusion mechanisms (i.e., briefly disabling interrupts)
    2. QF avoids mutex semaphores (no priority inversion)
    3. Minimizes need to block threads of active objects
      1. Wait for new events (normal)
      2. Wait for other active objects during RTC step (bad - avoid)
      3. Wait for occurences not related to other active objects (OK, sometimes necessary) (hazard: overflow event queue)
  • Event Passing
    1. Dynamic event allocation
    2. Communication using events: publish-subscribe model
      1. Published by generator of event
      2. Subscribed to by consumers of events
      3. Multicasting events: QF::subscribe()/unsubscribe(), QF::publish(), QF::propagate()
    3. Automatic event recycling: QF::annihilate()


Active Objects

  • Inheritance and Delegation
    1. is a QHsm
    2. has an event queue myEqueue
    3. has an execution thread
  • Critical Decisions
    1. Strategic: priority assignment
    2. Tactical: size of event queue
  • Policies
    1. Active objects do not share resources.
    2. Active objects interact only through post/subscribe of events.
    3. Active objects do not block during RTC processing to wait for each other.
    QActive Class Diagram


Running A System


Example: Dining Philosophers


QF API QR

The start method is the initializer for an active object. Note that the parameters each represent important decisions or processes that must preceed invocation:

int start
  (
    unsigned  prio,          // priority of active object
    QEvent *  qSto[],        // event queue (must allocate first)
    unsigned  qLen,          // size of event queue
    int       stkSto[],      // runtime stack
    unsigned  stkLen         // size of runtime stack
  );

The method run() is active throughout the life of the active object, analogous to main() in a standard single thread program. Note that there are two ways to post events directly to the object, LIFO (standard buffering) and FIFO (jump to the front of the queue).

Timer objects can be used as count-down timers via the fireIn() method, which fires after the number of ticks specified in the parameter nTicks and notifies by posting the signal specified in sig to the object specified in act.

Event Pool Data Structure

The event pools are classic free list implementation, using a fixed block of allocated memory. (Note, there may be faster models, in principle, but this is insignificant for relatively small pools.)

Note that these pools must be allocated as part of the startup, and event pool size is another tactical decision that must be made.

    Fig 9.2

    Event pool data structure


Event Queue Data Structure

The event queues are classic circular array implementation. Note that the items in the event queues are pointers to event base class, hence can hold the address of any event from any pool.

Again, a significant tactical decision is to determine the sizes of the event queues. The event pools are differentiated by the size of the event type. The event queues are associated with active objects.

    Fig 9.3

    Event queue data structure


Documentation and Directory Structure

    Online Documentation

    Book CD Directory Tree

    Code on CD

    Directory structure for multiplatform deployment of the QP libraries and QF applications