
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<thread_impl>). 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<thread_impl> (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" <pdimov@mmltd.net> 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<thread_impl>. 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.