Boost logo

Boost :

From: Bronek Kozicki (brok_at_[hidden])
Date: 2004-09-04 15:33:47


Hi

I factored out trampoline class from my ext_auto_ptr_090 . I'd like to
know how it works on modern compilers. I was able to test it on few
compilers I use for regression tests:
   msvc71 (passed with FAULTY set)
   como 4.3.3 with backend msvc71
   mingw 3.3.1
   mingw 3.4.1RC

I will be happy to know how it works with other compilers. Maybe
boosters could test this code with some compilers? I'm especially
interested in recent Intel and CW versions. I think that it might be
useful utility in boost, provided I can make it enough functional
(passing arguments to function is first thing to be added).

B.


#include <cassert>
#include <cstdio>
#include <utility>

// Copyright Bronislaw Kozicki 2003-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See http://www.boost.org/LICENSE_1_0.txt )

#ifndef __COMO__
# if defined(_MSC_VER) && (_MSC_VER <= 1310)
# define FAULTY
# endif // _MSC_VER
#endif // __COMO__

template <bool> struct static_assert;
template <> struct static_assert<true> {};

class trampoline
{
private:
  typedef void(*_pf_t)(void *);

  template <typename Functor>
  struct _lever_t;

  template <typename Functor>
  struct _lever_t<Functor *>
  {
    static_assert<sizeof(Functor*) == sizeof(void *)> size;

    union convert
    {
      Functor* f;
      void* p;
    };

    static void exec(void * p)
    {
      convert c;
      c.p = p;
      (*c.f)();
    }

    static std::pair<_pf_t, void *> init(Functor* f)
    {
      convert c;
      c.f = f;
      return std::pair<_pf_t, void *>(&exec, c.p);
    }
  };

// the one and the only data
  std::pair<_pf_t, void *> _pf;

public:
  template <typename Functor>
  trampoline(Functor f) : _pf(_lever_t<Functor>::init(f))
  {}

  trampoline(const trampoline& rh) : _pf(rh._pf)
  {}

  trampoline& operator=(const trampoline& rh)
  {
    _pf = rh._pf;
    return *this;
  }

  void operator()()
  {
    _pf.first(_pf.second);
  }
};

static int tmp = 0;

static const int tmp_f = 2;
void f()
{
  printf("f()\n");
  tmp = tmp_f;
}

static const int tmp_g = 5;
static const int tmp_g_f = 6;
#ifdef FAULTY
int g()
{
  int i = tmp_g_f;
  printf("faulty ");
#else
int g(int i = tmp_g)
{
#endif
  tmp = i;
  printf("g(%d)\n", i);
  return tmp;
}

static const int tmp_A = 10;
struct A
{
  void operator()() const
  {
    printf("A::operator()()\n");
    tmp = tmp_A;
  }
};

trampoline f1()
{
  return trampoline(&f);
}

trampoline g1()
{
  return trampoline(&g);
}

trampoline A1()
{
  static A a;
  return trampoline(&a);
}

int main()
{
  trampoline l = f1();
  l();
  assert(tmp == tmp_f);

  l = g1();
  l();
  assert(tmp == tmp_g || tmp == tmp_g_f);

  l = A1();
  l();
  assert(tmp == tmp_A);
}


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