view anagram/vaclgui/dispatch.hpp @ 15:f5acaf0c8a29

Don't cast through "volatile int". Causes a gcc warning nowadays. XXX: should put something else back here to frighten the optimizer
author David A. Holland
date Tue, 31 May 2022 01:00:55 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, A System for Syntax Directed Programming
 * Copyright 1997-2002 Parsifal Software. All Rights Reserved.
 * See the file COPYING for license and usage terms.
 *
 * dispatch.hpp
 */

#ifndef DISPATCH_HPP
#define DISPATCH_HPP

#include <ievent.hpp>


class AgDispatcher {
public:
  class Kernel {
  private:
    int useCount;
  public:
    virtual ~Kernel() {}
    virtual void dispatch(IEvent &) const = 0;

    Kernel() : useCount(0) {}
    void lock() { useCount++; }
    int unlock() { return --useCount <= 0; }
  };

protected:
  Kernel *kernel;

  AgDispatcher(AgDispatcher::Kernel *kernel_) :
    kernel(kernel_)
  {
    if (kernel) {
      kernel->lock();
    }
  }

public:
  AgDispatcher() :
    kernel(0)
  {}
  AgDispatcher(const AgDispatcher &a) :
    kernel(a.kernel)
  {
    if (kernel) {
      kernel->lock();
    }
  }
  AgDispatcher &operator = (const AgDispatcher &a) {
    if (kernel && kernel->unlock()) {
      delete kernel;
    }
    kernel = a.kernel;
    if (kernel) {
      kernel->lock();
    }
    return *this;
  }
  ~AgDispatcher() {
    if (kernel && kernel->unlock()) {
      delete kernel;
    }
  }
  void dispatch(IEvent &e) const {
    if (kernel) {
      kernel->dispatch(e);
    }
  }
};


template<class T>
class AgObjectDispatcher : public AgDispatcher {
  class Kernel : public AgDispatcher::Kernel {
    T &object;
    void (T:: * memberFunction)(IEvent &);
  public:
    Kernel(T &object_, void (T:: * memberFunction_)(IEvent &)) :
      object(object_) ,
      memberFunction(memberFunction_)
    {}
    void dispatch(IEvent &e) const { (object.*memberFunction)(e); }
  };

public:
  AgObjectDispatcher(T &object_, void (T:: * memberFunction_)(IEvent &)) :
    AgDispatcher(new AgObjectDispatcher<T>::Kernel(object_,memberFunction_))
  {}
  AgObjectDispatcher(const AgObjectDispatcher<T> &a) :
    AgDispatcher(a)
  {}
};


#endif /* DISPATCH_HPP */