Boost logo

Boost :

From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2003-01-09 12:22:42


"William E. Kempf" wrote:
[...]
> > I think that a reasonable requirement that we already mentioned several
> > times is that the ID should be CopyConstructible, Assignable and
> > LessThanComparable, for use in sets/maps.
>
> This misses the need for outputting in diagnostic messages, for one thing.
> And all of this can be supplied directly by boost::thread with no need for
> a boost::thead::id. I just want to make sure we've not missed some other
> need, which may mean we DO need a seperate id type.

I, for one, DO need something along the lines of:

http://groups.google.com/groups?selm=3D613D44.9B67916%40web.de
(Subject: Re: High level thread design question)

Well, "futures" aside for a moment, how about the following "concept"
(just an illustration/ideas):
 
  new_thread{< thread >}( function{, ...args...} );

  {exception_propagator< exception{, ...exceptions...} >::}
    {thread_attr_object.}new_thread( function{, args} );

  {exception_propagator< thread, exception{, ...exceptions...} >::}
    {thread_attr_object.}new_thread( function{, args} );

For example, given:

  void operation(); // Oh, BTW, in the next release this might throw std::bad_alloc

We could then have:

  a) no propagation of exceptions on join ["default"]:

       new_thread( operation );

       new_thread< my_fancy_thread >( operation );

       thread::attr().set_name( "007" ).
         new_thread( operation );

       my_fancy_thread::attr().set_something( something ).
         new_thread( operation );

  b) propagation of exceptions [specified at thread CREATION point] on join:

       exception_propagator< std::bad_alloc >::
         new_thread( operation );

       exception_propagator< my_fancy_thread,std::bad_alloc >::
         new_thread( operation );

       exception_propagator< std::bad_alloc >::
         attr().set_name( "007" ).
           new_thread( operation );

       exception_propagator< my_fancy_thread,std::bad_alloc >::
         attr().set_something( something ).
           new_thread( operation );

where "my_fancy_thread" would be something along the lines of:

  class my_fancy_thread : public thread {
  public:

    class attr : public thread::attr {
    public: /*...add some fancy stuff...*/ };

  /*...add some fancy stuff...*/ };

(with "thread fields", custom on_thread_start() and
 on_thread_termination() "hooks", etc. )

Basically, the idea is to use "exception_propagator" beast to communicate
the typelist of exceptions that need to be caught, stored and propagated
on join to the "thread" template -- it would simply have discriminated
union for storing result (void* for void functions; just to have
"something" instead of void) PLUS all exceptions from that typelist.

This typelist should be properly ordered and will be used for "generic"
catch-and-store-it-in-a-union "finalization" in the launching/landing
pad routine. Join operations would simply fire a "visitor pattern" to
throw this or that exception caught and stored in the joinee thread.

Generic code would have to be parameterized to let users specify a
typelist containing any exception types s/he wants to catch-and-
propagate-on-join for this or that async. "operation" invocation.

Well, I'd also probably could live with something along the lines of:
(ES: exception specification/throw({...})-spec; ES_stuff_only: things
specified in the ES excluding thread_cancel and thread_exit exceptions;
well, I'm somewhat unsure with respect to thread_restart exception ;-) )

  new_thread_that_will_propagate_on_join_ES_stuff_only( operation );

  new_thread_that_will_propagate_on_join_ES_stuff_only<
                                       my_fancy_thread >( operation );

  thread::attr().set_name( "007" ).
    new_thread_that_will_propagate_on_join_ES_stuff_only( operation );

  my_fancy_thread::attr().set_something( something ).
    new_thread_that_will_propagate_on_join_ES_stuff_only( operation );

but I don't think that this can be done in the current C++... its
standard-required-and-utterly-silly unwinding on ES violations aside
for a moment.

http://groups.google.com/groups?selm=3D514E1B.E3CF5716%40web.de
(Subject: Boost.Thread: "Threads & Exceptions"/"Enhanced call_once()")

Peter Dimov wrote:
[...]
> To put things in perspective:
>
> int foo()
> {
> return 10;
> }
>
> std::cout << boost::thread(foo).join() << std::endl;

Nah, < using namespace whatever >

int my_operation( int );

class my_fancy_thread : public thread {
public:

  class attr : public thread::attr {
  public: /*...add some fancy stuff...*/ };

/*...add some fancy stuff...*/ };

// called by thread::attr::new_thread<> function(s)
thread* create_thread_object( const my_fancy_thread::attr& );

// overloads NOOP defaults; called in the context of NEW thread
void on_thread_start( my_fancy_thread* );
void on_thread_termination( my_fancy_thread* );

void thread::main()
{
  joinable_thread_ptr< int,my_fancy_thread > pthread =
     my_fancy_thread::attr().set_system_contention_scope()
                            .set_sched_policy( sched::FIFO )
                            .set_fancy_blabla()
                            .set_initialy_suspended( true )
                            .set_daemon( true )
                            .new_thread( my_operation,
                                         some_magic_number );

  /*...*/
  pthread->start();

  // result is stored in joinable_thread_object< result,thread_type >
  // managed by smart thread ptr (thread_ptr<>/joinable_thread_ptr<>)
  int* presult = pthread->timedjoin( timeout::relative( 1000 ) );

  if ( thread::timedout( presult ) &&
       thread::canceled( presult = pthread->cancel().join() ) ) {

    cout << "OOPS: timedout and canceled!";

  }
  else {

    cout << "DONE: " << *presult;

  }

  return 0;

}

regards,
alexander.

--
http://groups.google.com/groups?selm=3E1C9A86.30F0FF41%40web.de

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