Boost logo

Boost :

From: Douglas Paul Gregor (gregod_at_[hidden])
Date: 2002-12-26 14:10:28


On Thu, 26 Dec 2002, Edward Diener wrote:
> "Douglas Paul Gregor" <gregod_at_[hidden]> wrote in message
> news:Pine.BSF.4.31.0212252228420.39075-100000_at_attempto.cs.rpi.edu...
> > On Tue, 24 Dec 2002, Edward Diener wrote:
> > > One should be able to order the call of slots when connecting them to a
> > > signal by saying that a slot should currently come first or last in the
> > > overall order without having to manually manufacturer low and high group
> > > numbers. This is especially so because disparate slots will not know
> about
> > > the group numbers of other slots in a signal-slot system.
> >
> > This could be simulated with an appropriate wrapper around the GroupName
> > template parameter. In fact, that is probably the best solution ("don't
> > pay for what you don't use" philosophy).
>
> In the doc I am looking at group numbers being passed in the
> boost::signal<>::connect function. I was thinking along the lines of
> 'connect(LAST,function_object)' or 'connect(FIRST,function_object)' perhaps
> using negative group numbers in your implementation. I don't know if this
> could be done or how much work it would take to do it.

The type of the group ordering is a template parameter, so group names
need not be numbers. To use a syntax such as the one you suggest, one
could use something like this class template:

enum sandwich_position { FIRST, MIDDLE, LAST };

template<typename T>
class sandwich
{
public:
  sandwich(sandwich_position pos) : value()
  {
    switch (pos) {
    case FIRST:
      position = --first;
      break;
    case MIDDLE:
      position = 0;
      break;
    case LAST:
      position = ++last;
      break;
    }
  }

  sandwich(const T& value) : value(value), position(0)
  {
  }

  bool operator<(const sandwich& other) const
  {
    return (position < other.position) ||
           (position == other.position && value < other.value);
  }

private:
  T value;
  int position;
  static int first;
  static int last;
};

template<typename T> int sandwich<T>::first = 0;
template<typename T> int sandwich<T>::last = 0;

It's not perfect (integer overflow will be a problem), but the basic
notion is that we can enforce a first/last ordering using a simple
wrapper. It should give the syntax and semantics you need.

> I was surprised that the normal connect, without group numbers, did not have
> the calling of slots in the same order as the connecting to a signal.

You're probably not the only person surprised by that :(. That property is
only due to an implementation decision (Signals use a multimap
internally), and I believe it does not represent the "best" interface we
could have. It seems that the underlying slot storage model really needs
to be parameterized: in some cases it is unnecessary to have any slot
ordering, in other cases a simple ordering suffices (e.g., your FIRST and
LAST suggestion), and in yet other cases a more powerful scheme (such as
the one currently implemented) is required.

> > > Borland has had a simple signal/slot mechanism in C++ Builder
> (__closures)
> > > at least 7 years previous to MS .NET's incarnation. Just thought you
> should
> > > know.
> >
> > Yes, Borland's event/closure mechanism should be mentioned. (It should
> > probably also be supported directly in Boost.Function, but that's another
> > matter).
>
> Supporting Borland's event/closure mechanism in Boost.Function might mean
> supporting an extension to C++. Perhaps Boost doesn't want to do things like
> that if they already have a good pure C++ way of doing things like
> Boost.Function and Boost.Bind along with Boost.Signal. Also, out of pure
> interest, Microsoft's latest VC++ .NET has their own __event mechanism
> extension for unmanaged C++ code which is slightly different than their
> 'delegate' mechanism for managed C++ .NET code ( and C# of course ).

There is nothing wrong with supporting an extension, so long as we do not
require the extension to use the library effectively. It's merely a
convenience for users that don't mind code that is not fully conformant
C++. Boost.Function could target .NET delegates and the __events as well,
if someone wants to contribute code and/or compiler for it :)

> I mentioned Borland only because your notes on other signal/slot
> implementations mentioned .NET 'delegates', which is fairly new, and
> Borland's '__closure' has been around for many years already. I always find
> it bemusing when people, for whatever reason, ignore Borland's earlier
> advanced conceptual ideas in favor of Microsoft's similar ones coming many
> years afterward. I think you may know that the person responsible for much
> of the language underpinnings of .NET and C# is the same person responsible
> for much of the design of Delphi/C++ Builder ( Anders Hejlsberg I believe
> his name is, although I may have the spelling wrong ). Anyway, all this is
> nether here nor there as far as Boost goes.

Ah. I omitted Borland's __closure mechanism from the documentation only
because it is not a mechanism for multicast callbacks like most
signal/slot systems. It's more like a subset of Function + Bind (or
Lambda) and not very much like Signals.

        Doug


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk