Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Next revision of boost::thread

0 views
Skip to first unread message

Alexander Terekhov

unread,
Jan 8, 2003, 4:39:18 PM1/8/03
to
< This is a sort of FYI with just a few comments added. The
OP can be found somewhere-in-the-moderated-boost-universe. >

"William E. Kempf" wrote:
>
> I've been working on the next release of Boost.Threads and would
> like to discuss the current design for the thread class. Here's
> a quick (and rough) description of the design. Note that much
> of this design is based on POSIX, for those familiar with it.
>
> class thread_cancel
> {
> public:
> thread_cancel();
> ~thread_cancel();
> };

What about thread_exit?

>
> #if defined(BOOST_THREAD_PRIORITY_SCHEDULING)

I'd rely on POSIX symbols. ;-)

>
> struct sched_param
> {
> int priority;
> // The rest of this structure is implementation defined
> };
>
> enum { sched_fifo, sched_rr, sched_other };
> enum { scope_process, scope_system };

Uhmm. Why not introduce a "sched" class/namespace?

>
> #endif // BOOST_THREAD_PRIORITY_SCHEDULING
>
> class BOOST_THREAD_DECL thread : private noncopyable

pthread_t IS >>copyable<<. The C++ "version" just ought to
be thread_ptr<>/joinable_thread_ptr<> (current_thread_ptr
aside for a moment).

> {
> public:
> class BOOST_THREAD_DECL attributes
> {
> public:
> attributes();
> ~attributes();
>
> #if defined(BOOST_THREAD_ATTRIBUTES_STACKSIZE)
> attributes& stack_size(size_t size);
> size_t stack_size() const;
> #endif // BOOST_THREAD_ATTRIBUTES_STACKSIZE
>
> #if defined(BOOST_THREAD_ATTRIBUTES_STACKADDR)
> attributes& stack_address(void* addr);
> void* stack_address() const;
> #endif // BOOST_THREAD_ATTRIBUTES_STACKADDR

Well, that's kinda "bad" POSIX, I guess.

>
> #if defined(BOOST_THREAD_PRIORITY_SCHEDULING)
> attributes& inherit_scheduling(bool inherit);
> bool inherit_scheduling() const;
> attributes& scheduling_parameter(const sched_param& param);
> sched_param scheduling_parameter() const;
> attributes& scheduling_policy(int policy);
> int scheduling_policy() const;
> attributes& scope(int scope);
> int scope() const;
> #endif // BOOST_THREAD_PRIORITY_SCHEDULING
> };
>
> thread();
> template <typename F>
> explicit thread(const F& threadfunc);
> template <typename F>
> thread(const F& threadfunc, attributes attr);
> ~thread();
>
> bool operator==(const thread& other) const;
> bool operator!=(const thread& other) const;

I want {attr.}new_thread<...>(<...>) factories and smart thread
pointers. Do you want a link? ;-)

>
> void join();

How would you report CANCELED condition? What about non-void
thread routines?

> void cancel();
>
> #if defined(BOOST_THREAD_PRIORITY_SCHEDULING)
> void set_scheduling_parameter(int policy, const sched_param& param);
> void get_scheduling_parameter(int& policy, sched_param& param) const;
>
> static int max_priority(int policy);
> static int min_priority(int policy);
> #endif // BOOST_THREAD_PRIORITY_SCHEDULING
>
> static void test_cancel();
> static void sleep(const xtime& xt);
> static void yield();
> };
>
> Several portions of this are conditionally compiled based upon the
> capabilities of the platform, with the following #defines used:
>
> * BOOST_THREAD_PRIORITY_SCHEDULING if the platform allows scheduling
> parameters to be set for a thread, such as priority.
>
> * BOOST_THREAD_ATTRIBUTES_STACKSIZE if the platform allows the stack
> size for new threads to be set by the user.
>
> * BOOST_THREAD_ATTRIBUTES_STACKADDR if the platform allows the stack
> address for new threads to be set by the user.
>
> class thread_cancel is a simple type thrown by cancellation points
> when a thread has been requested to be cancelled.
>
> struct sched_param is used to "portably" set the scheduling priority
> and other scheduling attributes. The only required member is
> "priority", used to specify a thread's priority. This design was
> borrowed from POSIX, and in fact the implementation uses the POSIX
> sched_param structure when BOOST_HAS_PTHREAD is defined.
>
> The sched_fifo, sched_rr, sched_other, scope_process, and
> scope_system values are implementation defined, and on POSIX
> correspond to SCHED_FIFO, SCHED_RR, SCHED_OTHER,
> PTHREAD_SCOPE_PROCESS and PTHREAD_SCOPE_SYSTEM respectively.
>
> thread::attributes::stack_size(size_t size) sets the size of the
> stack that will be created for a new thread constructed with this
> attribute object. If the implementation can't handle the specified
> size, std::invalid_argument is thrown.
>
> thread::attribute::stack_address(void* addr) sets the stack address
> that will be used for a new thread constructed with this attribute
> object.
>
> thread::attribute::inherit_scheduling(bool inherit) sets a flag
> indicating whether or not a thread created from this attribute
> object will inherit the current thread's scheduling attributes or
> will use the attributes found in this attribute object.
>
> thread::attribute::scheduling_parameter(const sched_param& param)
> sets the scheduling parameter used when creating a thread with this
> attribute object. The members and valid values of sched_param used
> depend on the policy set (see below). If invalid or unsupported
> values are set for any members std::invalid_argument is thrown.
>
> thread::attribute::scheduling_policy(int policy) sets the
> scheduling policy to be used. An implementation need not support
> the three documented policies (and in fact, may support a policy
> not documented, though generally this is what sched_other is for),
> and if an invalid or unsupported policy is specified
> std::invalid_argument is thrown.

Oh, yeah. Can you handle it?

>
> thread::attributes::scope(int scope) is used to set the scope of
> any thread created with this attribute object. If an invalid or
> unsupported scope is specified a std::invalid_argument is thrown.
>
> thread::thread() constructs a thread object that references the
> current thread of execution. If the current thread was not
> created by Boost.Thread's and resources can not be acquired by
> Boost.Threads for the current thread, thread_resource_error is
> thrown.

You better throw something a bit more specific [something along
the lines of std::bad_alloc and etc. ;-) ].

>
> template <typename F> thread::thread(const F& threadfunc)
> constructs a thread object that references a new thread of
> execution which executes threadfunc(). If any resources can
> not be allocated to do this, thread_resource_error is thrown.
>
> template <typename F> thread::thread(const F& threadfunc,
> attribute attr) constructs a thread object that references a
> new thread of execution created with the attributes specified
> in attr which executes threadfunc(). If any resources can not
> be allocated to do this, thread_resource_error is thrown.
>
> thread::~thread() reduces the ref-count on the referenced
> thread, and if the count is 0 (indicating no other thread
> objects reference the thread, and the thread has run to
> completion) cleans up all resources.
>
> thread::operator==() and thread::operator!=() are used to
> compare thread object's to determine if they reference the
> same thread of execution.
>
> thread::join() waits for a thread of execution to complete,
> and may be called multiple times with subsequent calls returning
> immediately.

Add also try/timed joins.

>
> thread::cancel() indicates that the thread of execution should
> throw thread_cancel at the next call to a "cancellation point".
>
> thread::set_scheduling_parameter() sets the scheduling policy
> and parameters for the referenced thread of execution. If an
> invalid or unsupported policy is specified, or if an invalid or
> unsupported value for any sched_param members is specified then
> a std::invalid_argument is thrown.
>
> thread::min_priority() and thread::max_priority() return the
> minimum and maximum values that may be set for a thread for a
> given policy, and is platform specific.
>
> thread::test_cancel() is a "cancellation point" and will throw
> thread_cancel if thread::cancel() has been called on the current
> thread of execution.
>
> thread::sleep() and thread::yield() have not changed, except
> they are now considered "cancellation points" and may throw
> thread_cancel.

"may" or "shall"? And, BTW, who needs yield()?

>
> I'd appreciate comments on the above design. Specifically I have
> these questions:
>
> * Are there concerns about using conditional compilation and
> optional portions of the library, as POSIX does? I believe this
> is the only way Boost.Threads and the C++ standard will be able to
> provide "portable" threading libraries that don't restrict
> implementation to a least common denominator approach.
>
> * Are there issues with throwing std::invalid_argument for both
> invalid and unsupported values? Should I define Boost.Threads
> specific exceptions instead, seperating out the two exception
> types?

Check out POSIX errors and define standard C++ exceptions for
everything that's really worth throwing/recovering... please,
leave any precondition violation(s) alone.

>
> * Should I not nest the thread::attributes class and instead
> have a boost::thread_attributes class?
>
> Beyond this, I'd appreciate any other feedback as well.
>
> William E. Kempf
> wek...@cox.net
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

regards,
alexander.

0 new messages