Boost logo

Boost :

Subject: Re: [boost] [thread] terminating destructor
From: Vicente J. Botet Escriba (vicente.botet_at_[hidden])
Date: 2012-10-25 13:03:18


Le 25/10/12 11:13, Andrzej Krzemienski a écrit :
> 2012/10/23 Vicente J. Botet Escriba <vicente.botet_at_[hidden]>
>
>>> Hi,
>> I have created two tickets to track this possible additions:
>>
>> https://svn.boost.org/trac/**boost/ticket/7540>:
>> Add a helper class that interrupts a thread and join it on destruction
>>
https://svn.boost.org/trac/**boost/ticket/7541>:
>> Add a thread wrapper class that interrupts and join on destruction
>>
>> While the scoped_thread class defined in C++ Concurrency in Action is a
>> strict scoped class that doesn't allows any change in the wrapped thread, I
>> think that making the interface thread compatible is also a good option.
>> This doesn't means that a strict scoped thread has no use.
>>
> Hi Vicente,
> The description in the two tickets above do not mention any interruption.
> thread_guard and scoped_thread only join w/o interruption. Do you intend
> both to interrupt before join?
>
> If "yes", will the names of the two would not be confusing? Name
> "scoped_thread" is likely (IMHO) to be interpreted that we want to finish
> for the thread to end in a normal (non-interrupted) way. Perhaps the name
> should indicate that we want an interruption.
>
> If "no", is scoped_thread different from the functionality offered by
> async? (Given that future's destructor blocks.)
>
>

I've been working a little bit these classes and I have not find that
interrupt-and-join on the destructor could be a a good compromise. As
others, maybe you, have signaled, each developer could need a specific
action on the destruction. As always been more generic means making the
class parameterized with a policy. A possible implementation could be

   /**
    * Non-copyable RAII strict thread guard joiner which join the thread
if joinable when destroyed.
    */
   class strict_thread_joiner
   {
     thread& t;
   public:
     BOOST_THREAD_MOVABLE_ONLY( strict_thread_joiner)

     explicit strict_thread_joiner(thread& t_) :
     t(t_)
     {
     }
     ~strict_thread_joiner()
     {
       if (t.joinable())
       {
         t.join();
       }
     }
   };

   /**
    * RAI @c thread wrapper adding a specific StrictThreadGuard allowing
to master what can be done at destruction time.
    *
    * StrictThreadGuard: A NonCopyable class that takes a @c thread& as
constructor parameter.
    * The default is a strict thread joiner guard.
    *
    * thread std::thread destructor terminates the program if the thread
is not joinable.
    * Having a wrapper that can join the thread before destroying it
seems a natural need.
    *
    * Example:
    *
    * boost::strict_scoped_thread<> t((boost::thread(F)));
    *
    */
   template <class StrictThreadGuard = strict_thread_joiner>
   class strict_scoped_thread
   {
     thread t_;
     StrictThreadGuard m_;
   public:

     BOOST_THREAD_NO_COPYABLE( strict_scoped_thread ) /// non copyable

     /**
      * Constructor from the thread to own.
      *
      * @param t: the thread to own.
      *
      * Effects: move the thread to own @c t and pass the stored thread
to an internal Destroyer.
      */
     explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) :
     t_(boost::move(t)),
     m_(t_)
     {
     }
   };

Now it is up to the user to change the default strict_thread_joiner policy.

I've implemented also a non-strict thread wrapper that behaves a thread
except that for the destruction.
Maybe need another name.

   /**
    * RAI @c thread wrapper adding a specific destroyer allowing to
master what can be done at destruction time.
    *
    * ThreadGuard: A MoveOnly class that takes a @c thread& as
constructor parameter.
    * The default is a thread_joiner guard.
    *
    * thread std::thread destructor terminates the program if the thread
is not joinable.
    * Having a wrapper that can join the thread before destroying it
seems a natural need.
    *
    * Remark: @c scoped_thread is not a @c thread as @c thread is not
designed to be derived from as a polymorphic type.
    * Anyway @c scoped_thread can be used in most of the contexts a @c
thread could be used as it has the
    * same non-deprecated interface with the exception of the construction.
    *
    * Example:
    *
    * boost::scoped_thread<> t((boost::thread(F)));
    * t.interrupt();
    *
    */
   template <class ThreadGuard = thread_joiner>
   class scoped_thread;

Does this respond to your question?

Best,
Vicente


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