Boost logo

Boost :

From: Kevlin Henney (kevlin_at_[hidden])
Date: 2000-08-09 10:41:14


In message <7D72C1B2F7A3D21191F8006097149AC0FFDBF6_at_S3>, Borgerding, Mark
A. <MarkAB_at_[hidden]> writes
>Just because a thread is implemented via a base class does not mean any
>absolute restrictions are imposed on a class hierarchy.

Unfortunately it does: if you wish to mix virtuals and member templates
you rapidly become unstuck and require an additional, exposed adaptor
type.

>A subclass of the base thread class can be used as an adaptor (GoF) to
>forward calls on to whatever object you give it at runtime.
>
>Example:
>
>class base_thread
>{
>protected:
> virtual int Run() = 0;
>};
>
>template <class T_Runnable>
>class adapter_thread : public base_thread
>{
>private:
> T_Runnable * m_pRunnable;
> virtual int Run() { return m_pRunnable->Run(); }
>};
>
>voila! You can create a adapter_thread<foo> where foo needs only to provide
>an function with signature "int Run()".
>adapter_thread<foo> supplies the virtual function that base_thread needs,
>and passes the call along to foo without requiring anything more than a
>Run() function.

But why should I have to specify the type of the runnable type at all?
The model I have in mind does not require this, and is simpler to use.

>The Run() function could be changed to something else -- maybe even made a
>template parameter.

If I understand you correctly, no it couldn't. (If not, then perhaps it
could ;->)

>My point is this:
> Using an abstract base class as the mechanism for implementing threads is
>the most straightforward method. And it imposes no real restrictions on
>what can be done (see above). If we start going off the deep end with
>functors and such just to make things as generic as possible, we will
>alienate the average programmer, for whom subclassing provides the most
>easily understood (and most commonly used) approach.

It is straightforward in that it is the traditional, pre-standard
approach. We do not need to go off the deep end at all, and I doubt very
much that we would alienate people; quite the opposite in fact:

void function()
{
        ... // thread lifecycle
}

struct function_object
{
        void operator()()
        {
                ... // thread lifecycle
        }
        ... // state and helpers to taste
};

...
{
        thread first, second;
        first(function);
                // starts first thread with function pointer its main
        second(function_object(...)); // ctor args as necessary
                // starts second thread with function object its main
        ...
}

Seems a lot easier to use than the inheritance-based approach.
____________________________________________________________

  Kevlin Henney phone: +44 117 942 2990
  Curbralan Ltd mobile: +44 7801 073 508
  kevlin_at_[hidden] fax: +44 870 052 2289
____________________________________________________________


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