Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2001-06-12 14:48:26


On Tuesday 12 June 2001 15:15, you wrote:
> williamkempf_at_[hidden] writes:
> | Actually, Boost.Function is required to get the deferred call
> | internally in create_thread(). That is, however, an implementation
> | detail. As a user all you need is a binder lib.
>
> Do I...
>
> This work with the code in the previous mail.
> It is possible that the binders I use is in reality a defer_call...
> but then I really don't see the difference between defer_call and a
> binder.

That's because "defer_call" intertwines the two ideas. Here is how I view the
components separately:

Boost.Function: does "defer" calls, per say, but is essentially a callback.
It contains a single function object (or function pointer). Invoking a
Boost.Function object invokes the function object it contains. This is
somewhat similar to a function pointer, but not exactly the same.

Binders: given a function object, create a new function object that, when
executed, passes some of its arguments and some arguments that were
previously "bound" to the underlying function object.

The difference is, essentially, that Boost.Function merely passes all of its
arguments through to the underlying function object. But, it can handle _at
run time_ any type of function object that is 'compatible' (i.e., given the
parameter types of the Boost.Function, each can be converted to the
corresponding parameter type of the underlying function object).

A binder may add or reorder arguments, but it only handles one kind of
underlying functor. The actual types of binders are rarely (if ever) known to
the user: they are implementation details and are created by calls to bind().

Each has its separate purpose - Boost.Function can be used just as a
generalized pointer, without binding any arguments. Binders can be used in
situations where the returned function object is passed as a template
argument and therefore doesn't matter. For instance, I can:

for_each(elements.begin(), elements.end(), (cout << free1));

(cout << free1 is Lambda-library syntax. It creates a function object that
calls the << operator with the first parameter bound to "cout" and the second
parameter to << is the parameter given to the function object).

In the above case, using defer_call would be a mistake because it is going to
require the overhead of a virtual call and prohibit what otherwise could be
inlined _very_ well.

> This code is very similar to the one I sent you some days ago.
>
> class thread_handle {
> public:
> explicit thread_handle(pthread_t p)
>
> : pth_(p) {}
>
> void join() {
> pthread_join(pth_, 0);
> }
> private:
> pthread_t pth_;
> };
>
>
> template <typename Functor>
> class ThreadArg {
> public:
> ThreadArg(Functor const & functor)
>
> : f_(functor) {}
>
> static thread_handle execute(Functor const & functor) {
> ThreadArg * arg = new ThreadArg(functor);
> pthread_t pth;
> pthread_create(&pth, 0, ThreadArg::start_routine, arg);
> return thread_handle(pth);
> }
> private:
> static void * start_routine(void * arg_v) {
> ThreadArg * arg = static_cast<ThreadArg*>(arg_v);
> arg->f_();
> delete arg;
> }
> Functor f_;
> };
>
>
> template <typename Functor>
> thread_handle create_thread(Functor const & functor)
> {
> return ThreadArg<Functor>::execute(functor);
> }
>
> | > Is there a binders lib proposed for boost that would allow me to do
> | > the above?
> |
> | The Lambda Library will allow constructs similar to this, but with a
> | richer syntax. I believe there's also a lighter weight binder
> | library in the files section.
>
> You wouldn't happen to know its name?

        Doug


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