Boost logo

Boost :

From: williamkempf_at_[hidden]
Date: 2001-06-26 15:14:00


I'm mulling over the design of the thread and thread_desc classes as
discussed in the earlier thread. I'm not totally sure where to go
with it, however, and thought I'd just throw some things out for
other people's input. The following is basically the design the
thread class will have:

    class thread : public boost::noncopyable
    {
    private:
        thread();
        ~thread();

    public:
        bool operator==(const thread& other);
        bool operator!=(const thread& other);

        bool is_alive() const;
        void join();

        static thread_desc create(const detail::threadfunc& func);
        static thread_desc self();

        static void join_all();
        static void sleep(const xtime& xt);
        static void yield();
    };

The create() and self() methods return a "thread_desc" instead of a
thread object, since the thread type is now noncopyable.
The "thread_desc" type is just a ref-counting descriptor for a thread
object. In other words, when thread_desc types are copied and
destroyed they modify a ref-count on the thread object, which is
destroyed when there are no more thread_desc objects referencing them
AND the thread has run to completion.

The question is, what's the design of thread_desc? Should it have a
smart pointer type of interface, or should the thread methods for
is_alive() and join() be static and take thread_desc parameters?

If it's a smart pointer interface I'd prefer to use a generic smart
pointer instead of a thread specific thread_desc class. However, I'm
not sure that boost::shared_ptr would be a good choice for this. I'd
rather use an intrusive ref-count just to insure it's not possible to
have to seperate ref-counts on an object. Further, shared_ptr would
have to be made thread safe, which though a good idea any way, leads
to a chicken and the egg sort of problem in development.

I'm also not sure that the following code "feels" quite right:

boost::thread_desc desc = boost::thread::create(&foo);
desc->join(); // This notation seems strange for a "descriptor"

So maybe such a design should use thread_ptr as the name instead?

If we don't go with a smart pointer approach but pass in the
thread_desc to the thread methods (join() and is_alive() so far) then
the thread class just becomes a sort of glorified namespace, which
doesn't quite feel right.

Yet another alternative would be to do away with the thread_desc idea
all together. In that case the constructor for thread would be the
creation routine and the destructor must either "join" the thread
or "detach" it (using pthread terminology instead of current
Boost.Threads terminology), and there will be little use for self()
and it's implementation would be problematic enough to warrant
removal. This design would still allow developers to manage threads
by creating them on the heap and storing them in what ever smart
pointers they wish to. This would be a well designed C++ solution,
but it differs enough from what programmers have grown to expect with
other APIs that it may not be a well liked solution.

Is there some other design I'm not thinking of as well?

Bill Kempf


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