Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2007-03-27 21:49:16


Howard Hinnant wrote:
> I'm coming full circle...
>
> As soon as I start allowing multiple threads to access std::thread at
> once, I need to keep a mutex around for the lifetime of the
> std::thread, whether or not it is already joined or even detached:

[...]

Here's how one possible N2184 thread looks to me:

class thread
{
private:

    n2178::handle handle_;

    thread( thread const & );
    thread& operator=( thread const & );

public:

    thread() {}

    template<class F> explicit thread( F f ):
        handle_( n2178::create( f ) )
    {}

    thread( thread && rhs ): handle_( std::move( rhs.handle_ ) )
    {
    }

    thread& operator=( thread && rhs )
    {
        handle_ = std::move( rhs.handle_ );
        return *this;
    }

    void swap( thread& rhs )
    {
        handle_.swap( rhs.handle_ );
    }

    void join() const
    {
        n2178::join( handle_ );
    }

    bool try_join() const
    {
        return n2178::try_join( handle_ ) != EBUSY;
    }

    bool timed_join( timespec const & abstime ) const
    {
        return n2178::timed_join( handle_, abstime ) != ETIMEDOUT;
    }

    void cancel() // const acc. to taste
    {
        n2178::cancel( handle_ );
    }
};

For cancel on destroy, add:

    bool cancel_on_destroy_; // initially true

    ~thread()
    {
        if( cancel_on_destroy_ ) cancel();
    }

    void detach()
    {
        atomic_store( &cancel_on_destroy_, true );
    }

There appears to be no need for a mutex in this prototype, unless I've
missed something.

Even if the actual implementation uses no n2178::handle, the above sketch
might still be useful as an illustration of the semantics and thread safety
that I have in mind. The omission of joinable() and cancel_requested() is
intentional, the omission of the rest of the members is for brevity,
although hardware_concurrency would probably be better off as a free
function.

To get back to an earlier statement of yours:

> This just leaves me with the feeling of implementing unique_ptr in
> terms of shared_ptr, at least on a pthreads platform.

Under my implementation at least, it's more like implementing
intrusive_ptr<thread_data> where the refcount can be at most 2 (std::thread
and the thread itself both holding a ref) in terms of
intrusive_ptr<thread_handle> with no refcount limit.


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