Chapter 23. Message dispatching-based thread design pattern

Index

Sending messages to the thread
The message dispatching thread loop
Stopping the execution thread
Generic stoppable interface
Using a stylesheet to generate a thread-based message dispatching framework
Stylesheet parameters
XML definitions
Optional message class constructor and serialization function
Generating doxygen documentation
GNU make macros
Using GNU make macros with automake
Using mcguffins with a message dispatching-based thread

x::msgdispatcherObj is a reference-counted object that implements a design pattern for a message-based thread class. An isolated thread runs in a loop that retrieves messages from other threads, and responds to them.

This design pattern contains several elements.

x::msgdispatcherObj implements the interface that constructs messages and puts them into a message queue by calling a pure virtual event(). A subclass implements event(). There are two available implementations. x::eventqueuemsgdispatcherObj is a subclass that uses an event file descriptor-based message queue and implemens event by putting the message into the event queue. x::dequemsgdispatcherObj is a subclass that uses a regular, mutex-protected, queue.

Public methods comprise the public interface to the class. Public methods take their parameters and package them into messages which are added to the message queue. The thread runs a loop that takes messages off the queue, and invokes the overloaded dispatch() method.

It's more convenient, in most situations, to use an XSLT stylesheet that takes a compact definitions of methods and their parameters. The stylesheet generates the code that defines the public methods which create the message classes, inserts the messages into the dispatching queue, and declares the dispatch() methods. The end result is conveniently #included into the class definition. But before getting to that, the following examples demonstrate the inner workings of x::msgdispatcherObj, and the mechanism that drives message dispatching.

#include <x/dispatchablemsgobj.H>

class myClass : public x::eventqueuemsgdispatcherObj {

    class mystatus {

    public:

        bool format;

        mystatus(bool formatArg) : format(formatArg)
        {
        }

    };

    class myrefresh {

    public:

        std::string name;

        myrefresh(const std::string &nameArg) : name(nameArg)
        {
        }

   };

  void dispatch(const mystatus &msg);

  void dispatch(const myrefresh &msg);

public:
  template<typename obj_type, typename msg_type>
      friend class x::dispatchablemsgObj;

  void statusinquiry(bool longformat);

  void refresh(const std::string &name);

  void run();
// ...

};

x::ref<myClass> clinstance(x::ref<myClass>::create());

x::run(clinstance);

This simple class defines two messages, statusinquiry and refresh (there's also a default stop message inherited from x::msgdispatcherObj), represented by two public methods.

Sending messages to the thread

void myClass::statusinquiry(bool longformat)
{
    sendevent<mystatus>(this, longformat);
}

void myClass::refresh(const std::string &name)
{
    sendevent<myrefresh>(this, name);

}

The x::msgdispatcherObj superclass defines the sendevent() template method. Its template parameter specifies the message class to send to the message-dispatching thread. Each message is a separate class.

The first parameter to sendevent() is a pointer to the class that defines the dispatch() method that receives the message class; in nearly all cases it's this. The pointer should not be an x::ref or an x::ptr. In most cases, the message queue is a member of the subclass, and consists of x::refs to unprocessed messages, and putting an x::ref or an x::ptr in each message creates a circular reference.

Using this is generally safe. If the message-dispatching object, and its thread, goes out of scope and gets destroyed, the unprocessed messages in the message queue also get destroyed, and their invalidated this never gets used.

The remaining arguments to sendevent get forwarded to the constructed message class instance's constructor.