|
Boost : |
From: Borgerding, Mark A. (MarkAB_at_[hidden])
Date: 2000-06-06 11:57:24
> -----Original Message-----
> From: Miki Jovanovic [mailto:miki_at_[hidden]]
> Sent: Tuesday, June 06, 2000 11:30 AM
> To: boost_at_[hidden]
> Subject: [boost] Re: RFC: Multithreading design constraints
>
> I have suggested a list before, and Beman asked for a thread to be
> included in it. I also think that is a good idea.
>
> Basic primitives:
> - thread
> - mutex
> - event
> - atom_traits
If we wanted to really scale it back; I believe mutex and atom_traits could
be implemented using events.
This would leave thread and event as the only primitives. But that might be
a bit severe.
>
> Mark also suggested a basic thread interface, but as noted before, I
> think we should get the requirements out before we get into interface
> design.
Agreed. I provided the interface mainly to illustrate concepts I had found
useful and problematic. The "highlights" section contains the design
principles that fell out of the iterative development of the class.
Sorry if I get ahead of myself sometimes. I am a practictioner first and a
theoretician second. I find it difficult to think about abstract theory
without some sort of skeleton on which to drape the sinew.
>
> This said, I don't know where else to start then to list the
> functionality each primitive needs to support. Please note, that I am
> not suggesting classes with following methods, but rather a concept
> that allows certain functions.
>
> thread:
> - start
> - stop
> - kill
> - join (with timeout)
> - set_priority (e.g. generic 1-10)
My only problem with dictating a fixed range (e.g. 1-10), is that some OSs
may have more priorites, others fewer.
The range of priority could be made dynamic by having functions or
enumerations that maintain the minimum, normal, and maximum thread
priorities. e.g.
int thread::min_priority()
int thread::max_priority()
int thread::normal_priority()
normal_priority could even be fixed as 0, leaving the user free to use
integer division to scale things back a bit like this:
myThread->set_priority( thread::min_priority() / 2 );
>
> mutex:
> - lock (allows recursion)
> - attempt_lock (with timeout)
> - unlock
>
> event:
> - set
> - reset
> - wait (with timeout)
>
> atom_traits
> - read
> - write
> - add
> - test_and_set
> - test_and_reset
> - compare_and_exchange
>
> OK, people, lets work the problem. Questions:
>
> - Do we need any other *basic* concepts?
I would like to see increment and decrement in atom_traits, but I suppose
those cases could be implemented via 'add'.
> - Is the event better choice then conditional variable, keeping in
> mind that events keeps its state, and can release a single waiting
> thread rather then all of them?
That depends on how the event is created.
Semantically, I like "event" best, because the name implies an action
occurring. However, I do like the "condition" part of c.v., it implies that
there are prerequisites that must be satisfied.
I suppose a name like "traffic_light" would be more descriptive, bringing to
mind an intersection where threads must wait for the light to turn green
before they can proceed.
I guess the name seems a bit silly, but perhaps no sillier than thunk,
thread, fiber, nice, socket, etc.
( I'm not really serious about coming up with a new name for the concept.
Neither event nor conditional variable is a completely accurate description
of the concept, but introducing another term may not help. )
> - Do we need to add/remove any functions on the primitives? (e.g.
> remove attampt_lock on mutex)
Neither Win32 critical sections nor pthreads (I think) have a primitive for
attempt_lock with timeout. However, either can emulate the operation to any
given precision by looping a sleep function and pthread_mutex_trylock or
TryEnterCriticalSection.
FWIW, I think the functionality is worthwhile, especially in dealing with
finicky resources or third party libraries that can't be debugged.
>
> mutex_guard:
> - constructor - locks the mutex
> - destructor - releases the mutex
> - acquire - locks the mutex if not already locked
> - release - releases mutex if not already released
>
> Is this correct representation of what was said? And do you have
> something to add to this?
Well, since you asked ...
I prefer lock & unlock over acquire & release. I think the term "lock" is
stronger and lock/unlock paradigm has been used in Windows (
CSingleLock::Lock & Unlock ) and pthreads ( pthread_mutex_lock &
pthread_mutex_unlock ).
- Mark
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk