|
Boost : |
From: Greg Colvin (gcolvin_at_[hidden])
Date: 2001-06-27 09:37:25
From: Beman Dawes <bdawes_at_[hidden]>
> At 10:06 PM 6/26/2001, Greg Colvin wrote:
>
> >> >Imagine a server that sits in a loop spawning threads to handle
> >> >incoming requests. When the request is handled the thread is
> >> >done, at which time any resources used by the thread need to be
> >> >released, pronto. So you need to create thread objects that will
> >> >magically disappear when they are done running.
> >> >
> >> >I started out to write a function to do this, and quickly began
> >> >to think it would be much easier for the thread class to provide
> >> >a utility for the purpose that returns shared_ptr<thread>.
> >>
> >> Isn't that what detach() is for? So after detach() has been called on
> a
> >> thread object, the underlying thread of execution is no long related to
>
> >the
> >> thread object, and delete can be called on the thread object
> immediately.
> >
> >So to do what I want I have to write
> >
> > thread* temp = new thread(handler);
> > temp.detach();
> > delete temp;
Actually, this could be just
thread(handler).detach();
so I'm happy enough, though I wonder if detach() isn't a
better default than join()?
> >whereas with native code I would just do
> >
> > CreateThread(0,0,handler,0,0,0);
> >
> >or in java
> >
> > new Thread(handler);
>
> [Aside: a number of common needs like the above have been identified in
> this discussion. I'll try to collect them so we can later show how our
> final solution would solve them.]
>
> Here is Bill's possible thread class:
>
> >It would simply be this:
> >
> > class thread : boost::noncopyable
> > {
> > public:
> > thread(const detail::threadfunc& func);
> > ~thread();
> >
> > bool is_alive() const;
> > bool join();
> > bool detach();
> >
> > static void join_all(); // This may be pointless!?
> > static void sleep(const xtime& xt);
> > static void yield();
> > };
> >
> >The destructor will call join() unless a call to detach() had been
> >previously made.
>
> Back to your example. Here are some possibilities:
>
> 1) new thread(handler).detach();
>
> 2) new thread(handler); // change dtor semantics: if (is_alive())
> detach();
>
> 3) new thread(handler, detach_option); // add ctor option
>
> 4) new detached_thread(handler); // add 2nd thread class
>
> I expect some of these are much better than others.
I think I see now that the 'new' is unnecessary given detach().
> >A harder example is keeping a list of all the running threads.
>
> Each time a thread is created, you stuff a pointer to it in a std::list,
> and the handler function is passed the iterator for the list entry. Before
> it exits, the handler function must call a function, passing the iterator
> as an argument, which erases the list element.
>
> >When I try actually writing such code I get confused real fast,
> >trying to be sure that the thread object has just the lifetime
> >I want.
>
> Seems like the worker function must cooperate for some uses, unless you are
> willing to poll is_alive() periodically.
Polling is a bad thing, and the rest sounds pretty complicated
compared to the
thread_ref thread::create(handler);
interface I posted where the thread_ref has useful copy semantics.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk