Thursday, December 8, 2011

window message dispatch generator

One goal for this dispatcher was to achieve pay-for-play performance characteristics. The generator builds a recursive type with a recursive dispatch function that only includes the message handling supported by the target. This produces a pretty concise if-else construct.

namespace detail {
template<typename WindowClassTag, typename Target>
struct generator_end
{
  typedef
    base<WindowClassTag, Target>
  type;
};

generator_end is used to terminate the recursive type being generated. base is defined previously but will be covered later.

template <
  typename WindowClassTag,
  typename Target,
  typename MessageChoice,
  typename Base = generator_end<WindowClassTag, Target >>
struct generator;

This is the prototype for generator, 2 specializations of generator are used to either add or omit a type from the recursive type.

template <
  typename WindowClassTag,
  typename Target,
  template <
    typename A,
    typename B,
    typename C > class MessageChoice,
  typename Base >
struct generator <
  WindowClassTag,
  Target,
  MessageChoice <
    WindowClassTag,
    Target,
    base<WindowClassTag, Target >> ,
  Base >
  : public Base
{
  typedef
    MessageChoice <
      WindowClassTag,
      Target,
      typename Base::type >
  type;
};

this specialization of generator matches when the target does support a message. It creates a type result using the supplied MessageChoice which is chained into the recursive type result (by changing the last template parameter to the result of the next recursed generator type result).

template <
  typename WindowClassTag,
  typename Target,
  typename Base >
struct generator <
  WindowClassTag,
  Target,
  nohandler,
  Base >
  : public Base
{
};

This specialization of generator matches when the target does not support the message (the nohandler class is already defined. nohandler will be described later.) There is no type defined here which ensures that no code will be generated for this message.

template <
  typename WindowClassTag,
  typename Target,
  typename Base >
struct generator_root
  : public Base
{
};
}

generator_root provides a container for the generator that allows the type to be stamped out by some macros.

template<typename WindowClassTag, typename Target>
struct generator {
  typedef
    typename detail::generator_root < WindowClassTag, Target
#   define WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR
#   include "win32_messages.h"
#   undef WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR

#   define WINDOW_MESSAGE_DEFINE_END_GENERATOR
#   include "win32_messages.h"
#   undef WINDOW_MESSAGE_DEFINE_END_GENERATOR
    >::type
  type;
};

This is how the type for a set of messages is created. This marco technique is complicated in order to allow the debugger to step through the dispatch code with source lines. WINDOW_MESSAGE_DEFINE_BEGIN_GENERATOR causes win32_messages.h to resolve to a recursive type for each message, while WINDOW_MESSAGE_DEFINE_END_GENERATOR causes win32_messages.h to resolve to a < for each type, this is required to finish the recursive generator definition.

Next is a look at the macro machinery..

No comments:

Post a Comment