I believe that we are going a bit off the topic here, but I'll go there with
you.
What you are suggesting, is that what we now know as 'thread' will be
transformed into 'thread_impl' and will be hidden from the user, which will
only know about thread_ref (actually a shared_ptr). First of
all, in no way do I dismiss this proposal. But what is the difference
between this and the current design? As explained in the Boost.Threads
documantation, if the user wish to control the life-time of the thread
object in such a way, he can always wrap it in shared_ptr himself. Do we
want to force him to work this way?
Another thing: if we want a
thread_ref current_thread();
function, how will it be implmented? I hope you don't mean the returned
thread to be non-joinable (which is a bad idea also in the current design),
so I'll assume you don't. To return a regular (joinable) thread we have to
hold a copy of each shared_ptr (increase the ref count by 1) in
an internal singleton data structure. That adds a considerable amount of
complexity to the implmentation, which is now nice and clean. It also raises
some questions, such as: When do we release the internal reference and allow
destruction of the thread_impl? Is it on join()? Maybe on thread execution
end? What if a thread is never joined? I presume that all these questions
can be reasonably answered, but still, it adds a factor of complexity.
The questions we have to ask ourselves are: Do we wan't to impose our memery
management decisions on the user? Does having a tight control over the
lifecycle of the thread object in the library's hand (rather than the
user's) is that important? Do we want to pay for it with a much more complex
implementation?
My personal opinion is to answer "no" to these questions. I'm quite fond
with the current noncopyable design (except the things I dislike, of
course), but that's just my opinion...
Note that both sides of the "noncopyable thread vs. shared_ptr thread_ref"
controversy agree that the basic thread class should be noncopyable. The
difference is: should it be wrapped in a shared_ptr before serving it to the
user, or not. So if you'll allow me to return to my initial claim from a few
messages ago, the thing is that a noncopyable class should not have an
operator== because it's inconsistent with the noncopyable notion. In
addition, the thread's no-parameteres constructor also violates this idea by
making a copy (of the current thread), and even making a bad copy
(non-joinable) of it... As a replacement, I'm suggesting the is_current()
member method to fulfill all of our desires, whether the thread is
shared_ptr<>ed or not.
"Peter Dimov" wrote in message
news:004601c4de17$807d5cd0$6401a8c0@pdimov2...
Yuval Ronen wrote:
[...]
According to your proposition, if I understood correctly, there is no
no-parameters constructor to thread, and all threads are joinable.
This is exactly what I was preaching to in my suggestion, so there is
no argument between us there. The difference is that you offer to add
a new thread_id class which I think is of no use at all. You need to
add some kind of connection between class thread and class thread_id,
something like: thread_id thread::get_thread_id(); // thread method
and then you'll go around and compare thread_ids. What for?
For
thread_id get_current_thread_id();
presumably.
If we agree that threads cannot be copied,
We don't. More details below.
it means that each thread can be
represented by only one thread object. Pass the address of thread
objects and compare them, if you really want to. It'll give you the
exact same result.
The problem with your reasoning is that the thread object may have been
destroyed. Its lifetime is not tied to the lifetime of the thread.
Threads are noncopyable for historical reasons. Bill Kempf's original
design had copyable, reference counted threads. Beman Dawes argued that a
thread is conceptually very similar to an fstream, so it should be
noncopyable, and Bill found his arguments convincing enough. I argued for
what seemed like an eternity that this is wrong, and the user should never
see a thread "object", only a thread handle (tentatively called thread_ref
at the time) - essentially a shared_ptr. The proposed API was
thread_ref create_thread( F f );
thread_ref current_thread();
void join( thread_ref tr );
I was unable to convince Bill Kempf to change the design (back), however.