|
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