However, its condition variable implementation should be avoided if one
can guarantee that one is using Windows NT and not DOS-Windows.
Uhmm. Interesting. Could you please elaborate?
regards,
alexander.
JdeBP> However, its condition variable implementation should be avoided if one
JdeBP> can guarantee that one is using Windows NT and not DOS-Windows.
AT> Uhmm. Interesting. Could you please elaborate?
If one can guarantee that one is using Windows NT and not DOS-Windows,
then many design constraints on a Win32 program disappear. Most notably
in this particular case, the principal (and pretty much only) reason for
not having a simple condition variable implementation, the lack of
SignalObjectAndWait() on DOS-Windows, goes away.
I assume that by "Dos-Windows" he means Win9x not Win30. Win9x does
have threads but does not support SignalObjectAndWait().
--
-Gary Chanson (MVP for Windows SDK)
-gch...@TheWorld.com
-War is the last resort of the incompetent.
SignalObjectAndWait() != POSIX condition variable,
to begin with... and, BTW, given:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q173260
("PRB: Synchronization Failure When Debugging (Q173260)")
that "entire" stuff is just yet another illustration
of "total brain-damage" principle that rules at MS
location...
regards,
alexander.
P.S. < quote from the link/PRB above >
"....
RESOLUTION
Placing Sleep(0) before the PulseEvent() or
SetEvent()/ResetEvent() calls will probably"
'probably' He he. ;-)
"avoid this problem, but this is not guaranteed
either. "
Ahhh. ;-) ;-)
"Unfortunately, there is no guaranteed workaround
for this situation.
...."
That's NOT true. There IS *pretty guaranteed* ;-)
"workaround for this situation":
No. DOS-Windows has had threads since DOS-Windows 95.
[...]
> http://support.microsoft.com/default.aspx?scid=kb;EN-US;q173260
> ("PRB: Synchronization Failure When Debugging (Q173260)")
>
> that "entire" stuff is just yet another illustration
> of "total brain-damage" principle that rules at MS
> location...
Did you read the article by keywords, such as "probably" and "no guaranteed
workaround", skipping the contents completely? If you did not notice, the
article says that while a thread is suspended, PulseEvent() will not wake
the thread, which is the intended and documented behavior:
[quoting Platform SDK]
[...] if no thread can be released immediately, PulseEvent simply sets the
event object's state to nonsignaled and returns.
[end quote]
Now how is that different from the KB article? The bottom line, PulseEvent()
works as it is advertised; that debugging is difficult is irrelevant.
S
I love the way Windows uses events rather than condition variables! The
fact that a "Signal" on an event isn't lost even though no-one's waiting
on it (while a condition variable signal does get lost) means you don't
have to wrap your brain around that horrendous
release-mutex-then-wait-then-reacquire-mutex command. Windows signals seem
way more natural.
--
Lucian Wischik, Queens' College, Cambridge CB3 9ET. www.wischik.com/lu
No; I did read it "completely".
> If you did not notice, the
> article says that while a thread is suspended, PulseEvent() will not wake
> the thread,
Not only PulseEvent. Read again.
> which is the intended and documented behavior:
*Intended* "brain-damage" is even WORSE than "accidental"
one. "Documented" is GOOD, though! ;-)
[...]
> Now how is that different from the KB article? The bottom line, PulseEvent()
> works as it is advertised; that debugging is difficult is irrelevant.
Irrelevant to what? That's exactly what makes this particular
piece of Win32 (among many others such pieces) *totally
brain-damaged*. Without that "feature", cond.vars. would be
fairly "simple" to implement/emulate (just an illustration):
http://groups.google.com/groups?as_umsgid=3AEAC433...@web.de
:>---------- Algorithm 1 ----------
:>given:
:>ex_mutex - mutex
:>cond - autoreset event
:>nWaiters - int
:>
:>wait(timeout) {
:> nWaiters++
:> bTimedOut=SignalAndWait(ex_mutex, cond, timeout)
:> lock ex_mutex
:> nWaiters--
:> return bTimedOut
:>}>
:>signal(bAll) {
:> do (bAll?nWaiters:1 times) {
:> PulseEvent(cond)
:> }
:>}
:>---------- ---------- ----------
:>This pseudocode assumes that ex_mutex is always held by the thread
calling
:>signal, ....
regards,
alexander.
My "usual ramblings" aside (see the beginning of that thread,
if you are interested[1] ;-)), check out this conversation
(and, please, don't miss the "coding exercise" ;-) ;-)):
http://www.codeproject.com/interview/herbsutter3032002.asp?forumid=3455&tid=131105&select=142170&fr=51#xx142170xx
(CV:"William E. Kempf" vs. EVENT:"Tim Smith" ;-))
HTH.
regards,
alexander.
P.S. Lucian, STUDY condvars (or, even better, the entire
pthreads altogether)! *You won't regret, really!*
I am interested. I taught condvars to students. I went to work at Compaq
SRC where they came up with one of the first real implementations of
condvars, partly because of that and because of their lovely language
Modula3. Coincidentally, the project I was working on there was proving
the correctness of programs written using Win32 primitives. Your "usual
ramblings" weren't a real argument, just bluster. The thread you pointed
me to was the same.
My experience was that win32 events were easier to program with because
they avoided the horrendous brain-twists needed to get around condvars. I
experience this brain-twist when teaching condvars to students. I haven't
taught win32 events yet. But when I figured out how to program the basic
multithreaded structures with events, I loved the solutions that were
possible.
So use SetEvent, which won't be!
PulseEvent smells like it was designed for one particular and bizarre
situation and isn't worth using in general because you don't encounter
that exact situation.
I'd agree that the main weakness of win32 events is that it's harder to
broadcast. And maybe people were trying (misguidedly) to use PulseEvent
for a broadcast. But I've found that different design of the
multithreading works better than trying to simulate the condvar broadcast.
If you use SetEvent on a manual event it'll release everyone waiting on it and
will leave the event in the "signalled" state till you ResetEvent. PulseEvent
will let go only one thread and reset the event. And in both cases if no one was
waiting, the signal occurrence will be lost.
> PulseEvent smells like it was designed for one particular and bizarre
> situation and isn't worth using in general because you don't encounter
> that exact situation.
>
> I'd agree that the main weakness of win32 events is that it's harder to
> broadcast.
Actually, I like Win32 events better than condition variables. You can broadcast
with a manual version. It's in general more straighforward to use, I think.
> And maybe people were trying (misguidedly) to use PulseEvent
> for a broadcast.
Not at all, it's there to release one thread on a manual reset event. With
pthreads you can't even guarantee such a thing, it's, unless I'm mistaken, at-
least-one thread release.
What do you mean "the signal occurrence will be lost"? The fact that it
was signalled has not been lost. So you must mean something else by
"occurence" but I don't know what.
> Not only PulseEvent. Read again.
Yeah, right. The pair of SetEvent()/ResetEvent() which is the same thing
given the usage scenario in question.
> *Intended* "brain-damage" is even WORSE than "accidental"
> one. "Documented" is GOOD, though! ;-)
Until you show what so _intrinsically_ brain damaged there is in
PulseEvent() this is, sorry, merely hot air.
> Irrelevant to what? That's exactly what makes this particular
> piece of Win32 (among many others such pieces) *totally
> brain-damaged*. Without that "feature", cond.vars. would be
> fairly "simple" to implement/emulate (just an illustration):
Excuse me. The world is not centered around the condition vars. Some types
may find it difficult to believe, but just assume that. Now, apart from the
conditional vars, or, more specifically, from the difficulty to broadcast
with Win32 events, what is so brain-damaged about them? You're trying to use
the tool that is not fit for the job, no wonder it hurts. If you do not know
how to go about without using events, ask, repeating that "one of Win32
mechanism is not a good foundation for X, so that Win32 mechanism is brain
damaged, and, BTW, the whole Win32 is brain damaged" will get you nowhere.
S
> If you use SetEvent on a manual event
...
> And in both cases if no one was
> waiting, the signal occurrence will be lost.
I believe this statement is wrong. According to MSDN:
The state of a manual-reset event object remains signaled until it
is set explicitly to the nonsignaled state by the ResetEvent
function. Any number of waiting threads, or threads that
subsequently begin wait operations for the specified event object
by calling one of the wait functions, can be released while the
object's state is signaled.
--
{michael}
I think it all depends on need. If all you need is to sleep until
signalled, then an event is an ideal solution. If, however, you have a
predicate that must be tested when you wake up, then that predicate
must be tested while holding the guarding mutex. And of course it
avoids having to think about most race conditions to combine
sleep/wake with lock acquire/release in one call (not all race
conditions, of course, the lost wake-up problem's still there if you
don't do it right).
To emulate that full behavior using only Win32 events requires the
guarding mutex, a manual-reset event, and a semaphore, and
understanding the "brain-twist" semantics anyway to avoid the race
conditions. For that, I'd rather just use a condition variable.
Having participated in an implementation of condition variables on
Win32, it was very difficult to get right. Having to write it all out
by ourselves made it clear exactly how it worked; however, it wasn't
worth it.
:-)
--
{michael}
Taken out of context, it is. I said if it's reset at some point before the wait.
WaitForEvent();
AcquireMutex();
test predicate
ResetEvent();
...
ReleaseMutex();
You can acquire the predicate after the event. So I don't understand why
you feel this "If..." is important.
>And of course it avoids having to think about most race conditions to
>combine sleep/wake with lock acquire/release in one call (not all race
>conditions, of course, the lost wake-up problem's still there if you
>don't do it right).
But I don't think you see the lost wake-up with events because it doesn't
get lost. Unless I misunderstand you.
This is not atomic. I think that's what he means. With cond vars you do that thing
above in one shot. When you wake up from the event you got your mutex taken out,
in Win32 you can't do that. It is a useful construct, but imo, it's not
sufficiently general to be elevated to an only available event-related API call.
That's why I think Win32, in general, is better (though it lacks the event/mutex
combination, just as it used to lack SignalAndWait construct; perhaps it should
be added to the API.)
I think it's stronger than that. With condvars you *HAVE TO* do the
release-mutex-then-wait atomically, else you might lose the event. With
events, you don't have to do it atomically, since the event remains
signalled.
Well, that's the same thing only backwards <g>. If you *need* such an operation,
then with pthreads there's a built-in construct. Win32 doesn't have it, and maybe
it should, but you should also be able to simply wait, w/o any mutexes involved.
That, unless I'm mistaken, pthreads don't allow, and I can't quite honestly,
figure why.
Care to show us some "solutions" you loved?
BTW, I figured out that MS-event is just:
a) mutex for locking;
b) silly "signaled" state -- only good for race conditions
(unless event is "protected" via yet another mutex/multi-
wait, or is completely disjoined from (does NOT mirror)
any "real" application state -- shared data, I mean).
c) "real" cond.var (plus that internal "signaled" predicate)
for waiting.
Here is the pseudo-code (w/o "pulsing" and thread cancellation
handling, though):
init event:
event->manual = <manual_mode>
event->signaled = <initial_state>
init event->mtx // mutex
init event->condvar // condition variable
end init event
wait for event:
lock event->mtx
while NOT event->signaled
cond_wait event->condvar,event->mtx
if NOT event->manual // Auto-reset
event->signaled = FALSE
unlock event->mtxLock
end wait for event
set event:
lock event->mtx
event->signaled = TRUE
unlock event->mtx
if event->manual
broadcast event->condvar
else
signal event->condvar
end set event
reset event:
lock event->mtx
event->signaled = FALSE
unlock event->mtx
end reset event
And (BTW too), "pseudo"-semaphore[1] (again, no-cancel):
init sema
sema->count = <initial_state>
sema->waiting = 0
sema->signaled = 0
init sema->mtx // mutex
init sema->condvar // condition variable
end init sema
lock sema
lock sema->mtx
if 0 == sema->count
++sema->waiting
do
// either ignore signal-"stealing" which
// could occur due to spurious wakeups/
// timeouts (for timedlock) or just add
// some extra checking/handling here and
// in unlock
cond_wait sema->condvar,sema->mtx
while 0 == sema->signaled
--sema->signaled
else
--sema->count
unlock sema->mtx
end lock sema
unlock sema
lock sema->mtx
if 0 == sema->waiting
++sema->count
unlock sema->mtx
else
--sema->waiting
++sema->signaled
unlock sema->mtx
signal sema->condvar
end else
end unlock sema
regards,
alexander.
[1]
http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap04.html#tag_04_15
(see "Semaphore"/"Semaphore Lock Operation"/"Semaphore Unlock
Operation"
and, perhaps:
http://groups.google.com/groups?selm=3CDBD51B.3B7839F8%40web.de
Ok. No problems, "pardon" is given (feel free to
punish yourself -- via using brain-damaged events ;-)).
> The world is not centered around the condition vars. Some types
> may find it difficult to believe, but just assume that.
I assume that. Even more: unfortunately, the world (really
large population) IS centered around brain-damaged events;
I do realize it, Slava.
> Now, apart from the
> conditional vars, or, more specifically, from the difficulty to broadcast
> with Win32 events,
Huh?
> what is so brain-damaged about them?
They have state (unless you just "pulse" permanently
"nonsignaled" auto-reset ones [making it stateless,
in effect] emulating STATELESS condvars, thread-
suspension/debug problems aside). That's it. That
"extra" state sort-of-mirrored in the events is
A) absolutely useless for "waiting" w.r.t. some
"real" state change reflected in some shared
data,
and
B) really easy/prompt to introduce race condition,
like MS-folks themselves CONTINUE to demonstrate
here, for example:
http://sources.redhat.com/ml/pthreads-win32/2001/msg00158.html
(silly MSDN articles, I mean)
regards,
alexander.
Yep.
> else you might lose the event.
Nah. *signal* -- else you might fail to unblock
"the right" <awaiting, if any> thread... do a
search on "terekhov tennis" ;-).
> With
> events, you don't have to do it atomically, since the event remains
> signalled.
And that's exactly what makes them totally
brain-damaged, right! ;-)
regards,
alexander.
Could you please show us your impl (it is fairly simple
thing with thread-specific "blockers"/explicitly managed
queue)?
> Having to write it all out
> by ourselves made it clear exactly how it worked; however, it wasn't
> worth it.
> :-)
Why?
regards,
alexander.
Right (and intelligence and/or skills ;-)).
> If all you need is to sleep until
> signalled, then an event is an ideal solution.
If all you need is a simple monitor with a boolean state
variable, then just do it -- mutex (for locking), state.var
(shared data that is "monitored" and "controlled" by your
application), and cond.var (for waiting) packaged together
in some "event" structure is all what you need to make it
"work". It is simple (but NOT often needed [in my experience],
though).
regards,
alexander.
Lucian Wischik wrote:
>
> josh <jo...@xtreme.net> wrote:
> >On 14 May 2002 06:45:14 GMT, ljw...@cus.cam.ac.uk (Lucian Wischik) wrote:
> >> WaitForEvent();
> >> AcquireMutex();
> >This is not atomic. I think that's what he means. With cond vars you do
> >that thing above in one shot.
>
> I think it's stronger than that. With condvars you *HAVE TO* do the
> release-mutex-then-wait atomically, else you might lose the event. With
> events, you don't have to do it atomically, since the event remains
> signalled.
>
You're right that you *HAVE TO* hold the mutex to do a wait. It was deliberately
designed that way to force, err..., I mean encourage, proper multithreaded programming
practices.
But stronger wouldn't be the right term to use. Think in terms of lower level primitives
and higher level constructs. You wouldn't call assembly language stronger than java. Each
has its place. The lower level primitive to do non-lossy signaling without locks would be
something like eventcounters which pthreads doesn't have. (note to others: constructing
a lower level primitive out of higher level constructs somehow isn't the same thing).
Win32 doesn't have eventcounters either. The problem with win32 events, if I remember correctly,
is that it's problematic to have multiple waiters on the event. If you do it gets really
nasty coordinating the resetting of the event properly, or else you have possible race or
hang conditions being ignored, possibly out of cluelessness. And generally you don't hear
win32 programmers complaining of the former all that much.
Joe Seigh
Lucian Wischik wrote:
>
> Alexander Terekhov <tere...@web.de> wrote:
> >My "usual ramblings" aside (see the beginning of that thread,
> >if you are interested[1] ;-)), check out this conversation
> >(and, please, don't miss the "coding exercise" ;-) ;-)):
> >P.S. Lucian, STUDY condvars (or, even better, the entire
> > pthreads altogether)! *You won't regret, really!*
>
> I am interested.
I am too.
> I taught condvars to students.
Uhmmm. Really? "No comments". ;-)
> I went to work at Compaq
Oh! That's just yet ANOTHER really GOOD reason why you should
buy a book written by one of your former colleagues... and it
could really help you w.r.t. "teaching condvars to students",
I guess!
> SRC where they came up with one of the first real implementations of
> condvars, partly because of that and because of their lovely language
> Modula3.
You mean: (*Alert*: "HIGHLY RECOMMENDED READING", folks)
http://gatekeeper.research.compaq.com/pub/DEC/SRC/research-reports/SRC-020.ps.gz
http://216.239.39.100/search?q=cache:cv84gdXblOIC:gatekeeper.research.compaq.com/pub/DEC/SRC/research-reports/SRC-020.ps.gz
(text version; BTW: Joe, they even mention "eventcount"! ;-))
> Coincidentally, the project I was working on there was proving
> the correctness of programs written using Win32 primitives.
Rather silly project, IMHO. The usual outcome is already known
to "everyone and his dog" out there -- mostly *INCORRECT*; just
check out MSDN "publications"! ;-)
> Your "usual
> ramblings" weren't a real argument, just bluster. The thread you pointed
> me to was the same.
Yeah, for example:
"I've given you the proof, but you've not "wanted to see the
forest for the trees". Tim, please, I know you're smart and
I respect your opinions, so it's a shame that things are very
rapidly spiraling into flame territory. Try to objectively
listen to what I've said and then try and prove me wrong. You
insist on proof from me, but this is one of those scientific
topics in which absolute proof isn't possible. I've laid the
ground work, however, for you to prove me wrong. If you can't
do so then my assertion is correct, because I'm not claiming
that it's impossible, only that no one's done it yet which
makes the event "unsafe" in this context.
So... here's the ground work. Let's take the simplest "hello
world" MT example that we've all done numerous times, the
classic "bounded buffer". Show me an implementation using
only mutexes and events (actually, to prove that events are
"safe" you'd probably have to do this with a single event
and a single mutex, but I'll let you use any number of these
you care to) that is free of race conditions. Heck, if you
think the classic example is somehow specifically designed
to be problematic for events I'll settle for *any* example
that uses only events, mutexes and some shared resource. If
you can prove me wrong you'll make my life soooo much easier,
so believe it or not I'm rooting for you to succeed.
William E. Kempf"
> My experience was that win32 events were easier to program with because
> they avoided the horrendous brain-twists needed to get around condvars.
"horrendous brain-twists needed to get around condvars"
aside, PLEASE demonstrate to us that "win32 events were
easier to program with" using Bill's "ground work", for
example.
regards,
alexander.
I cannot; it was for a proprietary product. In fact, I don't work
there anymore so I can't even look at the code...
:-(
However, it pretty much followed the designs available in papers that
can be found via Google. A waiter count guarded by a mutex, the
"outer" mutex of the monitor, and a semaphore of waiters.
> > Having to write it all out by ourselves made it clear exactly how
> > it worked; however, it wasn't worth it.
> Why?
Because it was a cross-platform product, therefore it required using
the same semantic regardless of platform. We chose to do this in terms
of condition variables, with a trivial implementation on *nix systems,
but we then had to develop, maintain, and ensure through significant
testing that we had exactly the same behavior for the nontrivial Win32
implementation.
Joe Seigh <jse...@genuity.com> writes:
> The problem with win32 events, if I remember correctly, is that it's
> problematic to have multiple waiters on the event. If you do it
> gets really nasty coordinating the resetting of the event properly,
This one I'll agree with. It's established elsewhere in this thread
that if you try the construct:
* lock mutex
* test predicate
* unlock mutex
* go to sleep on event
that the event could be signalled between the two steps. To prevent
that signalling being lost, a manual-reset event is needed. However,
once you do that, there's no way to restrict it to only one thread
being released (ie, pthread_cond_signal as opposed to
pthread_cond_broadcast).
At least MSDN didn't imply any way to do it.
:-)
--
{michael}
> Care to show us some "solutions" you loved?
> BTW, I figured out that MS-event is just:
> c) "real" cond.var (plus that internal "signaled" predicate)
> for waiting.
There exists a "real" cond.var implementation inside Win32? Now that'd be
great, if there were only a way to access it...
--
Arnold Hendriks <a.hen...@b-lex.com>
B-Lex Information Technologies, http://www.b-lex.com/
> Ok. No problems, "pardon" is given (feel free to
> punish yourself -- via using brain-damaged events ;-)).
Looks like it's your favorite style -- take a couple of words out of
context, demonstrate how clever you are by exploiting the out-of-context
phrase and, when reminded of the context, switch the topic completely, as
you did with debugging and suspending. Typical smoke and mirrors practice,
the weapon of choice in religious debates. Back on the topic. I asked to
excuse me "for interrupting your stream of eloquence as having no relation
to events whatsoever". "Because events are not conditional variables nor
were they designed to be suitable for implementing the latter." I hate to be
so explicit but apparently I will have for a while.
As others have said a dozen of times in this thread, events are one thing
and conditional variables another thing. Events are conceptually simpler
than condvars [e.g., you don't need an external mutex with events]. Events
may come more handy in certain situations [e.g., wait on multiple events:
try that with condvars when the sources do not cooperate]. Finally you can
implement conditional variables without ever touching events [having
diagonally scanned the long article you referenced yesterday, I can tell
you know that]. I am not commenting on your demonstrating of events'
brain-damagedness as you again slipped to comparing them to conditional
variables... it is true that some people like oranges so much that they hate
apples, but I find comparing both quite fruitless.
I completely accept and share the viewpoint that Win32 events may be
unexpectedly difficult to use in specific applications and many
implementations using events have subtle problems. PulseEvent() is
especially hard to get right for the uninitiated. That MS is as prone to
that as everybody else is of little surprise... [damn I said I wouldn't
comment :-)]. I will still maintain that for other applications events are a
perfect fit. I could mention a few cases but as you are unlikely to stop
using your favorite "brain-damaged" idioms I should better save myself that
typing.
S
Excuse me (BTW, feel free to "exploit" this couple of words ;-)),
but I don't understand your "switch topic" bit w.r.t. "as I did
with debugging and suspending". Could you please elaborate?
> Typical smoke and mirrors practice,
> the weapon of choice in religious debates
I'm a smoker (do you remember BELOMOR/PRIMA/etc.? ;-))
and even heard of mirrors, but never heard of that
debating practice. How about e-mail on that, Slava?
> Back on the topic.
That's good (BTW, compare the number of words
in our off-topic-blah-blah' portions ;-)).
> I asked to
> excuse me "for interrupting your stream of eloquence as having no relation
> to events whatsoever". "Because events are not conditional variables
See below.
> nor were they designed to be suitable for implementing the latter."
Uhmm. Whether they were designed to be suitable or not, they
COULD be used for implementing/emulating the latter, AFAICT.
> I hate to be so explicit but apparently I will have for a while.
Ok. That always helps... presuming that you'll succeed in
achieving that goal. ;-)
> As others have said a dozen of times in this thread, events are one thing
> and conditional variables another thing.
I also said *exactly that* -- did I say that cond.vars
ARE brain-damaged and/or error-prone? I think: NO! ;-)
> Events are conceptually simpler than condvars
That's wrong.
> [e.g., you don't need an external mutex with events].
But you DO need "internal mutex"... to communicate the
state of shared "flag" (and associated application shared
data) among different threads (processors -- hint: "memory
sync".), to begin with; apart from "blocking" - with NO
clear separation between "locking" and "waiting" (see POSIX
threads Rationale), etc.
> Events may come more handy in certain situations [e.g.,
> wait on multiple events: try that with condvars
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Oh <sigh>... My, *WaitForMultiple*... Don't get/provoke
me on this, please. FYI:
http://groups.google.com/groups?selm=slrn7hiau9.1q3.kaz%40ashi.FootPrints.net
(*HTH*, I especially like "...president of the United States." bit ;-))
> when the sources do not cooperate].
Uhmm. What do you mean? If "sources do not cooperate"
they simply AREN'T threads -- what are you talking
about?
> Finally you can
> implement conditional variables without ever touching events
Well, MS-auto-reset event is also known to ABM-world as BIN.SEMA
(pulsing aside), to begin with. And, semas (and MS-ones with that
silly/brain-damaged "max" count, especially) aren't really much
better than events *for shared memory (with it, I mean) cooperative
sync.protocols and threading: "medium to fine-grained structuring
mechanism for parallelism in an application" (signals/interrupts
aside)*. Read the POSIX threads Rationale on semas, please (I've
already posted the {indirect} link somewhere in this thread, and,
BTW, that old DEC-SRC research paper also mentioned it).
> [having
> diagonally scanned the long article you referenced yesterday, I can tell
> you know that].
I'm not sure what you imply by "that", really.
> I am not commenting on your demonstrating of events'
> brain-damagedness as you again slipped to comparing them to conditional
> variables... it is true that some people like oranges so much that they hate
> apples, but I find comparing both quite fruitless.
OK. See below.
> I completely accept and share the viewpoint that Win32 events may be
> unexpectedly difficult to use in specific applications and many
> implementations using events have subtle problems. PulseEvent() is
> especially hard to get right for the uninitiated. That MS is as prone to
> that as everybody else is of little surprise... [damn I said I wouldn't
> comment :-)]. I will still maintain that for other applications events are a
> perfect fit.
That's really interesting...
> I could mention a few cases but as you are unlikely to stop
> using your favorite "brain-damaged" idioms I should better save
> myself that typing.
Slava, I *PROMISE* NOT TO USE "brain-damaged" idioms
(and, heck, even ";-)" idioms) in my replies to your
followup(s) that would *really show a few cases where
events are a perfect fit*.
Please!
Deal? ;-)
regards,
alexander.
On Tue, 14 May 2002 20:35:35 +0200, "Slava M. Usov" <stripit...@gmx.net>
wrote:
> "Alexander Terekhov" <tere...@web.de> wrote in message
> news:3CE0C501...@web.de...
>
> > Ok. No problems, "pardon" is given (feel free to
> > punish yourself -- via using brain-damaged events ;-)).
>
> Looks like it's your favorite style -- take a couple of words out of
> context,...
> Excuse me (BTW, feel free to "exploit" this couple of words ;-)),
> but I don't understand your "switch topic" bit w.r.t. "as I did
> with debugging and suspending". Could you please elaborate?
I started following this thread when it was crossposted to
microsoft.public.win32.programmer.kernel. The message that drew my attention
was the one where you cited the KB article dealing with PulseEvent() and
debugging, with some annotations :-). My only objection to that was and
still is that there is no point in citing that article as if it violated
some agreement between programmers and MS, since MS _had_ put all the
relevant details in the synopsis of that API routine. I do not really care
much about events being inferior or superior to condition variables, they
are just different. That's another thing that I stand by. While you always
end up comparing the two. So. Now you do not say that "events are bad
because threads can be suspended" [for me, this is ridiculous since they are
pretty much independent of each other], now you mention other things --
fine, you may have a point, but I never wanted to discuss that, for the
reason I explained above.
> I'm a smoker (do you remember BELOMOR/PRIMA/etc.? ;-))
Gave up a few years ago, after a major dental overhaul and lots of horror
smoke-tar-high-temperature-teeth stories told by the dentist. The bills sort
of confirmed his narrative :-). And yes I remember that stuff, how is it
possible to forget it? :-)
> and even heard of mirrors, but never heard of that
> debating practice. How about e-mail on that, Slava?
OK
> Uhmm. Whether they were designed to be suitable or not, they
> COULD be used for implementing/emulating the latter, AFAICT.
Yes, and the emphasis is proper. And you could use a nuke to deal with seeds
in your garden.
> > [e.g., you don't need an external mutex with events].
>
> But you DO need "internal mutex"... to communicate the
> state of shared "flag" (and associated application shared
> data) among different threads (processors -- hint: "memory
> sync".), to begin with; apart from "blocking" - with NO
> clear separation between "locking" and "waiting" (see POSIX
> threads Rationale), etc.
Not necessarily. Events may be used to communicate things without any
synchronization at all [OK, events _are_ a synchronization mechanism, but
here I'm using the word in the narrow sense of having two or more threads
interlock]. A simple example that I see every other day in the real world
software: a thread that does things periodically. That thread must terminate
upon some condition. The archetypical Win32 idiom for that is an event for
"time to quit" and WaitForSingleObject() with a timeout for periodical
wake-up. You could do the same with a condvar, but it takes another boolean
variable, to say nothing of the mandatory ex_mutex. Events are conceptually
simpler in _this_ case.
> Oh <sigh>... My, *WaitForMultiple*... Don't get/provoke
> me on this, please. FYI:
>
>
http://groups.google.com/groups?selm=slrn7hiau9.1q3.kaz%40ashi.FootPrints.ne
t
> (*HTH*, I especially like "...president of the United States." bit ;-))
Good points, but not very convincing. For the one place of sleeping, this is
exactly how NT kernel is implemented, but that place may have a variable
length list of waitable dispatcher objects, and when one of them becomes
signaled it is quite simple for the scheduler to wake the thread if it is an
"any" wait, or traverse the whole list it is the an "all" wait. When I say
"variable length" it is indeed so; the 64 objects limitation is artificial
and probably comes from the inability to communicate larger numbers in the
status code returned by the native API, which is [yes!] silly.
For the starvation, a nice try, but if you're using that, you should think
of that, right?
Not scaling is hardly an issue, as there is seldom a need to wait for more
than just a handful [fixed, at that] of objects.
Then there are many things ultimately saying "not portable", but if I don't
care about that?
The advice to make an aggregate object is good [I anticipated that] but that
is not always possible. Say, if you're doing NT-style async IO, you can't.
If you just using somebody else's code which gives you the handle to wait
on, you can't. If you're waiting on an object exported by a separate process
[by its name], you can't. Granted it may be possible if the design of all
the components takes that into the account, but we are being realistic here,
right?
> Uhmm. What do you mean? If "sources do not cooperate"
> they simply AREN'T threads -- what are you talking
> about?
Sources of events. Code the sets/resets them. See the previous paragraph.
> Well, MS-auto-reset event is also known to ABM-world as BIN.SEMA
> (pulsing aside), to begin with. And, semas (and MS-ones with that
> silly/brain-damaged "max" count, especially)
Well. Then just use 0x7fffffff for that.
> aren't really much
> better than events *for shared memory (with it, I mean) cooperative
> sync.protocols and threading: "medium to fine-grained structuring
> mechanism for parallelism in an application" (signals/interrupts
> aside)*. Read the POSIX threads Rationale on semas, please (I've
> already posted the {indirect} link somewhere in this thread, and,
> BTW, that old DEC-SRC research paper also mentioned it).
I've read that but events already are more than I can handle in this
discussion [short of time, sorry].
> > [having
> > diagonally scanned the long article you referenced yesterday, I can tell
> > you know that].
>
> I'm not sure what you imply by "that", really.
Only that you know that events may be avoided for condvars implementation,
thus eliminating another reason to compare them.
> Slava, I *PROMISE* NOT TO USE "brain-damaged" idioms
> (and, heck, even ";-)" idioms) in my replies to your
> followup(s) that would *really show a few cases where
> events are a perfect fit*.
>
> Please!
>
> Deal? ;-)
Deal. An example above.
S
Again, the problem here is NOT limited to PulseEvent(), the fact
is that SignalObjectAndWait is pretty much useless given the way
how MS implements their "thread model" that allows {annotations}
async.suspend; has {annotations} "suspended" thread state (which
even "break out"[1] already *blocked/waiting* threads) as a part
of their {annotations} thread-model (apart from completion ports
thread pooling -- w.r.t. {annotations} I mean).
I'll reply later (I'm just too busy now/today) to the rest of
your points, but for now, I'd like to "just" drop the following
microsoft.public.win32.programmer.kernel link (and your are quite
familiar with this stuff, Slava... hint: "don't you ever do it"):
http://groups.google.com/groups?threadm=3c4c58b2.21267811%40news.lineone.net
(Subject: Thread synchronization issues)
regards,
alexander.
P.S.
> Now you do not say that "events are bad because threads can be suspended"
In a way, *I DO*.
P.P.S.
http://groups.google.com/groups?threadm=3c4f2281%241%40news.microsoft.com
"....
In win32 you can do it with SignalObjectAndWait (if you use mutex
for locking). "
Well, practically, *you can't* (using SignalObjectAndWait).
"Unfortunately, there is no simple way that
I know of to do this with critical sections."
I know really simple way to do "this" -- click here:
http://sources.redhat.com/pthreads-win32
(see condvars... and, BTW, check out *timed*
"crit.sections" there as well.)
----
[1] Compare/consider (somewhat related thing, IMO):
http://www.opengroup.org/onlinepubs/007904975/functions/pthread_cond_wait.html
(please don't miss the "RATIONALE" section, "Performance of...", etc. --
HTH)
"....
If a signal is delivered to a thread waiting for a condition
variable, upon return from the signal handler the thread resumes
waiting for the condition variable as if it was not interrupted,
or it shall return zero due to spurious wakeup.
...."
http://groups.google.com/groups?selm=1104_1013803235%40js3owsj2-2j2-2j
"From: josh (jo...@xtreme.net)
Subject: Re: Can multiple threads set a global variable simultaneously?
Newsgroups: comp.programming.threads
Date: 2002-02-15 16:59:23 PST
Thanks.
On 15 Feb 2002 06:32:35 -0800, tere...@web.de (Alexander Terekhov)
wrote:
...."
> Kick him in the ass.
"pardon" is given (and, btw, there are much better places to kick,
stupid).
regards,
alexander.
> Again, the problem here is NOT limited to PulseEvent(), the fact
> is that SignalObjectAndWait is pretty much useless given the way
> how MS implements their "thread model" that allows {annotations}
> async.suspend; has {annotations} "suspended" thread state (which
> even "break out"[1] already *blocked/waiting* threads) as a part
> of their {annotations} thread-model (apart from completion ports
> thread pooling -- w.r.t. {annotations} I mean).
Well, that is a completely different angle. Win32 threading has some
shortcomings, I cannot deny that nor can I blame them for that. They were
more or less pioneers in this field. Before Win32 there had been just a
handful of OSes supporting threads natively, and they all were experimental
or in limited use. For that matter, all implementations that use kernel
threads are, as you say, {annotated}; scheduler activations might be a
better approach to threading-enabled OSes: at least they would provide for a
painless implementation of any imaginable synchronization primitive
completely in user mode.
[...]
>
http://groups.google.com/groups?threadm=3c4c58b2.21267811%40news.lineone.net
> (Subject: Thread synchronization issues)
So? In that thread I never said PulseEvent() or events were anything
different than they are. I'm not saying what you think I'm saying; I'm
saying that I'm compltely satisfied with the way PulseEvent() works, even
though it, well, can rarely be used [and one needs to understand what is
being done]
> > Now you do not say that "events are bad because threads can be
> suspended"
>
> In a way, *I DO*.
That should read "threads are bad", then; regarding that, see above.
[...]
> "Unfortunately, there is no simple way that
> I know of to do this with critical sections."
>
> I know really simple way to do "this" -- click here:
>
> http://sources.redhat.com/pthreads-win32
Yeah, yeah. But then there are semaphores, not events. Indeed, semaphores
are more sensible here, since you always deal with a known number of
waiters, so you don't have to decide who's going to call ResetEvent() and
handle the race conditions it will involve. PulseEvent(), regardless of
thread suspends, can be only used with SignalObjectAndWait(), which is not
portable in Win32 [I wouldn't care, though], plus you must use a
heavy-weight mutex for that.
One thing I don't like about that code, though, is the wait enter/exit
sequence: a gate/internal mutex is acquired, and when it gets pathological,
there are more... lots of contexts switches when there is contention.
S
"Slava M. Usov" wrote:
> ...]
> Well, that is a completely different angle. Win32 threading has some
> shortcomings, I cannot deny that nor can I blame them for that. They were
> more or less pioneers in this field. Before Win32 there had been just a
> handful of OSes supporting threads natively, and they all were experimental
> or in limited use. [...
Could you explain that a little more? As someone who was doing "multi-threading"
before there was a DOS 1.0 even, I am really curious.
Joe Seigh
> > more or less pioneers in this field. Before Win32 there had
> > been just a handful of OSes supporting threads natively, and
> > they all were experimental or in limited use.
> Could you explain that a little more? As someone who was doing
> "multi-threading" before there was a DOS 1.0 even, I am really
> curious.
Name your operating system and application of the pre-DOS 1.0 days,
and the number of deployed systems. Also note the "natively" word, which
means in kernel mode and not the LWP-way. That I think will explain it
far better than I can. Besides, "doing stuff" in not the same as "having
huge accumulated experience in stuff [which allows creation of real good
stuff]".
S
Well, IBM's MVS for one. It had shared memory. An event signaling mechanism
using wait(), post(), and an ecb (event control block) which resided in
shared memory and which had a similar problem with that of win32 events. Sharing
it among multiple waiters was a problem.
Ignorance of prior art doesn't mean there wasn't prior art. It just means that
you get entertaining usenet postings and not so entertaining operating systems.
Joe Seigh
Yeah... "LWP-way" ;-) FYI:
http://groups.google.com/groups?selm=3CC6BDBF.C7CD1A02%40web.de
("Subject: Re: First OS with threads support")
HTH.
regards,
alexander.
Do you _work_ for Microsoft?...
> Do you _work_ for Microsoft?...
Your point being?
S
[...]
> Well, IBM's MVS for one. It had shared memory. An event signaling
> mechanism using wait(), post(), and an ecb (event control block)
> which resided in shared memory and which had a similar problem with
> that of win32 events.
OK, having a few thousand installations in the world probably qualifies for
a scope larger than "limited". However, the bit on "an event signaling
mechanism" nullifies the whole point: MVS had that, and they had just the
same. I'd like to hear of something that did the right thing, was well
known, relatively widely deployed, and all that ca 1985. If I'm not
mistaken, what was called OS/2 was started at about 1987, a branch of which
later on became NT. I'm not surprised by this similarity between MVS and NT
given the history.
Really, the question is not that hard. By that time, ignoring MVS for the
moment, they might only borrow from VMS or some pure or mixed Unix variant.
VMS, AFAIK, did not have threads by that time; IIRC, they were working on
DECthreads, which later on became POSIX threads. The threading model of NT
had been decided on before that, I believe. What was going on in the Unix
community and academia I do not even want to mention: even if you wanted to
borrow something you could hardly decide what.
S
[...]
> http://groups.google.com/groups?selm=3CC6BDBF.C7CD1A02%40web.de
> ("Subject: Re: First OS with threads support")
It wasn't very long ago that Sun officially decided that LWP
might be used by applications directly as threads. Before that, there had
been probably some obstacles. What is happening with Linux _today_
concerning threads and "LWP", I don't want to know, thank you. So, whatever
reason one has for calling their threads LWP means they are different from
threads.
S
Hmm, that's not a no. ;-)
> "Joe Seigh" <jse...@genuity.com> wrote in message
> news:3CE3A44F...@genuity.com...
>
>
>>>more or less pioneers in this field. Before Win32 there had
>>>been just a handful of OSes supporting threads natively, and
>>>they all were experimental or in limited use.
Excuse me!?! That is revisionist history! The real-time embedded software
industry has been using multiple threads per shared address-space for
multiple decades, long before the release of any Win32 product. The pioneering
work in the computer software industry regarding bringing
multiple-threads-per-shared-address-space products successfully to the
commercial marketplace were the widely-deployed real-time operating systems
(RTOSes) in the late 1970s and early 1980s (plus a large amount of truly
pioneering pre-fully-commercial research/experimental-work 1.5 to 2 decades
before that).
>>Could you explain that a little more? As someone who was doing
>>"multi-threading" before there was a DOS 1.0 even, I am really
>>curious.
>>
>
> Name your operating system and application of the pre-DOS 1.0 days,
> and the number of deployed systems. Also note the "natively" word, which
> means in kernel mode and not the LWP-way. That I think will explain it
> far better than I can. Besides, "doing stuff" in not the same as "having
> huge accumulated experience in stuff [which allows creation of real good
> stuff]".
>
> S
pSOS (a.k.a., pSOSystem, later named pSOS+) was an RTOS from Integrated
Systems Incorporated (now owned by WindRiver Systems) introduced in the early
1980s which has had as its main claim to fame, since its early days, 1)
richly-expressive multiple-threads-per-shared-address-space, 2) synchronization
mechanisms between those threads, and 3) asynchronous
multiproducer-multiconsumer unit-of-work hand-off mechanisms between threads
(a.k.a., message-queues). If you have ever made a telephone call or used the
Internet, your communication is likely to have been carried across continents &
oceans by at least one network-element running pSOS+ internally. Many military
products also run pSOS+ internally. Following 1960s-era conventions in the
multiple-threads-per-address-space research which referred to threads as
"processes" or "tasks", threads are called tasks in pSOS which was one of the
commercially-viable & wide-deployed RTOSes to appear during the late 1970s &
early 1980s. I think that we all agree that the telephone network and military
systems were widely deployed before Win32.
UNIX System V Release 4.1MP (and its related bretheren UNIX SVR4.2, UnixWare,
and Solaris 2.X) with UNIX International threads (i.e., before POSIX real-time
extensions and before Win32's threads) shipped in 1992 if I remember correctly.
Throughout the 1990s versions of UNIX & Solaris incorporated the features
and/or source code from UNIX SVR4.1MP. I think that we all agree that Sun
workstations running Solaris 2.X were widely deployed before Win32.
Mentor Graphics' VRTX (pronounced "vertex") and WindRiver's VxWorks are also
RTOSes whose multiple-threads-per-shared-address-space capabilities have been
used on software embedded within telecommunications & military equipment for
multiple decades. If you have ever made a telephone call or used the Internet,
your communication is likely to have been carried across contitents & oceans by
at least one network-element running VxWorks internally. Many military products
also run VxWorks internally. I think that we all agree that the telephone
network and military systems were widely deployed before Win32.
VRTX: http://www.mentor.com/embedded/vrtxos/
VxWorks & pSOS: http://www.windriver.com/products/html/os.html
The following excerpt is from
http://www.faqs.org/faqs/os-research/part1/section-10.html
"On a side note, threads have been in continuous use in telecommunications
applications for quite a long time."
where "quite a long time" is in presented in the context of discussing the
history of threads prior to existence of UNIX in the early 1970s.
Evidence of RTOS tasks predating the 1980s & 1990s emergence of the
popularity of threads in Mach, UNIX SVR4, and Win32.
http://groups.google.com/groups?q=RTOS+tasks+history&hl=en&lr=&selm=36701227.548B7573%40lapel.com&rnum=2
http://www.dedicated-systems.com/encyc/publications/faq/rtfaq.htm
Evidence that RTOSes' use of the term "task" for what is now popularly called
"thread" in general-purpose operating systems predates the term "thread":
Evidence of tasks being a long-standing feature in VxWorks along with a
history of VxWorks that obviously predates Win32:
Evidence that RTOSes are widely deployed, forming an entire long-standing
sizable industry:
Evidence that real-time operating systems had threads/tasks long before 1989:
http://groups.google.com/groups?q=RTOS+threads+earliest&hl=en&lr=&selm=33724547.14B%40expresslogic.com&rnum=4
"
> For academics, see also Rajkumar, Sha, Lehoczky, "An Experimental
> Investigation of Synchronization Protocols", Proc. 6th IEEE workshop on
> Real-Time Operating Systems and Software, p.11-17, May 1989. As far
> as I am aware, the earliest publication of the algorithm was in a paper
> by Lampson and Redhill in 1980. For a history of the research in this area,
> see Audsley, Burns, Davis, Tindell, and Wellings, "Fixed Priority Preemptive
> Scheduling: An Historical Perspective", Real-Time Systems 8(3),
> pp. 173-198 (1995).
"
-----------------------
By the way, to all people who think that Microsoft invented or popularized
technologies which appared in Windows95, Windows98, WindowsNT, Windows2000, or
WindowsXP:
Pre-emptive operating systems with multiple separate-address-space processes
were invented decades ago (not merely years ago in Win32 or even OS/2).
Pre-emptive multiprocess OSes were widely deployed by many computer vendors in
many product lines decades ago (not merely years ago in Win32 or even OS/2).
In fact at one time the largest single commercial vendor of a version of UNIX (a
preemptive multitasking operating system) was Microsoft themselves who sold
Xenix in the early 1980s. Microsoft sold Xenix to Santa Cruz Operation in the
first half of the 1980s, leaving Microsoft with a predominantly single-threaded
single-process operating system: MSDOS. In the early 1980s Gary Kildall's
Digital Research and Bill Gates's Microsoft were competing head to head on two
operating systems fronts: 1) DRI's CP/M versus Microsoft's DOS in the category
of single thread, single process operating systems for microcomputers and 2)
DRI's Microport UNIX versus Microsoft's Xenix in the category of preemptive
multiprocess operating systems.
Multiple threads-of-execution per shared address-space was invented
decades ago (not merely years ago in Win32). Multiple threads-of-execution
within one shared address-space was widely deployed in real-time embedded
systems decades ago (not merely years ago in Win32).
Graphical user interfaces on single-user computers were invented decades ago
in the 1970s (not in the mid1980s with the first release of MSWIN 1.0 running on
top of MSDOS). GUIs on single-user computers were widely deployed by Sun,
Apollo, Apple, and to some degree Xerox and others by the early 1980s.
Would you sleep better if it were a no? And you sound as if yes might be a
bad thing...
S
> Excuse me!?! That is revisionist history! The real-time embedded
> software industry has been using multiple threads per shared address-
> space for multiple decades, long before the release of any Win32
> product.
Different story altogether. I said about multiple threads in multiple
address spaces, and most RTOSes had one address space, in which multiple
tasks may execute. For that reason, we may also quote MS-DOS as a
multithreaded system, in which it was an elementary matter to have multiple
tasks running [TSRs and device drivers]; unless you tried to perform IO
simultaneously, you could get away with that, and later on MS added some
undocumented or partly documented [I don't remember the details now] API
which would actually allow you to switch tasks and do some limited IO. This
was exploited by network redirectors and Windows, and is still being
exploited by Windows ME.
Actually I don't even care about who first invented and who first
implemented and whose's generically "bigger". :-)
I can take back the word "pioneer" if you are unhappy about that. But in
mainstream application programming threads had little appearance, if any,
before Win32. Most of the RDBMS on UNIX and VMS normally had multiple
processes and not multiple threads well into 90s. Same applies to other
types of network servers. I hear it was different on mainframes, though.
[...]
> UNIX System V Release 4.1MP (and its related bretheren UNIX SVR4.2,
> UnixWare, and Solaris 2.X) with UNIX International threads (i.e., before
> POSIX real-time extensions and before Win32's threads) shipped in 1992
> if I remember correctly.
Do not forget that most concepts of Win32 started to take shape in 1987 when
the work on OS/2 started. I have an ntexapi.h [posted by somebody on USENET
a few years ago] which contains declarations of most of NT's native API, in
particular, all of the synchronization primitives. Here is its header:
Copyright (c) 1989-1993 Microsoft Corporation
Module Name:
ntexapi.h
Abstract:
This module is the header file for the all the system services that
are contained in the "ex" directory.
Author:
David N. Cutler (davec) 5-May-1989
[end header]
That means they started working on that stuff at least in 1987, and so they
could only use things invented at least a couple of years before that, i.e.,
until 1985, as more or less accepted in the industry [or in the development
team even]...
To the rest of your points, the answers are identical.
S
> "Daniel Miller" <daniel...@tellabs.com> wrote in message
> news:3CE53FA0...@tellabs.com...
>
>
>> Excuse me!?! That is revisionist history! The real-time embedded
>>software industry has been using multiple threads per shared address-
>>space for multiple decades, long before the release of any Win32
>>product.
>>
>
> Different story altogether. I said about multiple threads in multiple
> address spaces, and most RTOSes had one address space, in which multiple
> tasks may execute.
Excuse me for being insistently correct, but you were definitely not
emphasizing anything interprocess/multiprocess-intraprocessor in any way. You
were talking about who pioneered commercially-deployed viable-in-the-marketplace
MT software designs & MT operating systems for MT software in general---i.e.,
software whose execution model is multiple threads-of-control within a shared
address-space. Those commercial pioneers would be the telecommunications
industry, the military contractor industry, and other embedded software
industries using commercial-off-the-shelf (COTS) real-time operating systems
(RTOSes), since the late 1970s & early 1980s who in turn based their work on
still earier pre-commercial research. Furthermore before using COTS RTOSes,
these industries used their own proprietary internally-developed RTOSes. [Many
companies in those industries today still use legacy proprietary RTOSes
developed during the 1970s or 1980s in some of their older products.]
Multithreaded software within one process running on a
single-process-per-processor operating system
is overwhelmingly the same as
multithreaded software within one process running on a
multiple-processes-per-processor operating system.
Same mutexes (a.k.a. binary semaphores).
Same Dijkstra/counting semaphores.
Same read-write locks.
Same asychronous (multi)producer-(multi)consumer message-queue delivery
mechanisms needed.
Same need to address in-coming asynchronous events & interrupts on some one
or more threads.
Same bugs due to two or more threads stepping on each other due to lack of
thread-synchronization or sufficient asynchronous unit-of-work hand-off via
message-queues.
Same bugs due to leaks of semaphore release/increment.
Same bugs due to leaks of mutex release.
Same research base.
Same solutions.
Same software designs.
Same problems with MT.
Same benefits deriving from MT.
Same priority-inversion considerations.
The only way which I consider them different with respect to
multithreadedness is that a few RTOSes do not have the following (whereas other
RTOSes do):
1) forking/spawning child processes (because RTOSes do not have processes
*plural*)
2) shared memory between different address-spaces (because RTOSes do not have
address-spaces *plural* until one considers the *interprocessor* case)
3) *interprocess-intraprocessor* thread-of-control synchronization (until one
considers the *interprocessor* case via networking protocols)
4) *interprocess-intraprocessor* asynchronous (multi)producer-(multi)consumer
message-queues for unit-of-work hand-off (until one considers the
*interprocessor* case via networking protocols)
Most people who work on MT software can go years without even realizing that
such interprocess-intraprocessor concepts exist to complement their
interthread/intraprocess concepts which they use every day.
> Actually I don't even care about who first invented and who first
> implemented and whose's generically "bigger".
This is not about one-upmanship competition. This is about how to stand on
the shoulders of giants who came beforehand in the multi-decade-old MT software
industry: the embedded real-time systems industry.
I encourage everyone to do a direct head-to-head feature-by-feature
comparison of VxWorks's or pSOS's multithreaded feature-set to Win32
multithreaded feature-set. If one is diligent, such an investigator will find
one common theme: most of the general-purpose operating-systems still to this
day emphasize
1) thread-*synchronization* (which tends to erode MT architectures down to
blocking-architecture status, not achieving sufficient concurrency)
over
2) *asynchronous* unit-of-work hand-off via (multi)producer-(multi)consumer
message-queues (which tend toward nonblocking architectures achieving far
greater concurrency).
There are still some things even after all these *decades* that the
general-purpose/hosted software world can learn from the embedded real-time
software world with respect to multithreaded software designs which we have
pioneered & honed over many years. That is, only if you admit that we exist in
the first place and have a multi-decade multithreaded knowledge-base built up in
our sector of the industry.
"Slava M. Usov" <stripit...@gmx.net> wrote in message news:<eaSF1Qd$BHA.2384@tkmsftngp02>...
[...]
> Do not forget that most concepts of Win32 started to take shape in 1987 when
> the work on OS/2 started. I have an ntexapi.h [posted by somebody on USENET
> a few years ago] which contains declarations of most of NT's native API, in
> particular, all of the synchronization primitives. Here is its header:
>
> Copyright (c) 1989-1993 Microsoft Corporation
>
> Module Name:
>
> ntexapi.h
>
> Abstract:
>
> This module is the header file for the all the system services that
> are contained in the "ex" directory.
>
> Author:
>
> David N. Cutler (davec) 5-May-1989
^^^^^^^^^^
>
> [end header]
>
> That means they started working on that stuff at least in 1987, and so they
> could only use things invented at least a couple of years before that, i.e.,
> until 1985, as more or less accepted in the industry [or in the development
^^^^^^^^^^
> team even]...
>
> To the rest of your points, the answers are identical.
Ok. Slava, how about this:
http://groups.google.com/groups?selm=3BE7ABD3.6303D8E1%40web.de
"Saul wrote:
>
> Hi
>
> I've seen a couple of times posts (at this newsgroup) along the lines:
> "The use of events (As opposed to condition variables) for
> synchronization of threads is hard to use correctly"
> It was also noted that the comparison of events & cv's was studied in
> the 1970's.
...."
also:
http://groups.google.com/groups?selm=wnxF7.1274%24RL6.32514%40news.cpqcorp.net
and, perhaps:
http://groups.google.com/groups?selm=3CE51E06.94C040E2%40web.de
Slava, do you still have any more questions/remarks?
regards,
alexander.
FWIW, I work for IBM (Germany) and would consider "work" for
Microsoft as a BAD THING with respect to "better sleep". ;-)
Well, but *REALLY BAD THING* is that Mr. Butenhof {still} DOES
*NOT* WORK for US (IBM)... given the "New HP"-mess/opportunity,
I mean. ;-) ;-)
regards,
alexander. < speaking here for only-myself; NOT IBM and/or anyone else >
Again, that's WRONG.
> Same Dijkstra/counting semaphores.
Read the papers/quotes on original-monitors/archaic-cond.vars,
better (POSIX threads ) cond.vars, etc. I've posted somewhere
in this *exciting* thread. ;-)
> Same read-write locks.
> Same asychronous (multi)producer-(multi)consumer message-queue delivery
> mechanisms needed.
> Same need to address in-coming asynchronous events & interrupts on some one
> or more threads.
> Same bugs due to two or more threads stepping on each other due to lack of
> thread-synchronization or sufficient asynchronous unit-of-work hand-off via
> message-queues.
> Same bugs due to leaks of semaphore release/increment.
^^^^^^^^^
Don't use them.
> Same bugs due to leaks of mutex release.
Use C++/RAII/mutex locking guards.
> Same research base.
> Same solutions.
> Same software designs.
> Same problems with MT.
> Same benefits deriving from MT.
> Same priority-inversion considerations.
^^^^^^^^^^^^^^^^^^
Yeah... and, again: SEMAs don't really "help" here either.
regards,
alexander.
http://groups.google.com/groups?selm=3CE26636.2069C71B%40web.de
("...I'll reply later... to the rest of your points...")
> now you mention other things --
> fine, you may have a point,
Does this mean that you now AGREE that condvars ARE
much BETTER than {annotations} events and semaphores?
> but I never wanted to discuss that, for the
> reason I explained above.
>
> > I'm a smoker (do you remember BELOMOR/PRIMA/etc.? ;-))
>
> Gave up a few years ago, after a major dental overhaul and lots of horror
> smoke-tar-high-temperature-teeth stories told by the dentist. The bills sort
> of confirmed his narrative :-). And yes I remember that stuff, how is it
> possible to forget it? :-)
Yeah... "molodost'":
dvor, dacha-derevnya, pionerskije-camps, sport-sections,
dvojki-peterki, peremenki, diskoteki, tur-poxodi, uchilki,
komsomolki, dekan, <one-year-army-almost-blackout... samovolki,
naraydi, silly-prapora/guba, etc.> kartoshka, studentki,
vzlad-tv, muz-oboz, diplom, rod-dom-svad'ba-patom...
perestrojka/zagranka. aahh...well.
> > and even heard of mirrors, but never heard of that
> > debating practice. How about e-mail on that, Slava?
>
> OK
>
> > Uhmm. Whether they were designed to be suitable or not, they
> > COULD be used for implementing/emulating the latter, AFAICT.
>
> Yes, and the emphasis is proper. And you could use a nuke to deal with seeds
> in your garden.
Oh! Agreed. MS-events ARE NUKES (silly/archaic generation,
only good to play "politics" and really dangerous w.r.t.
leaks to "terrorists"/rogue-states/etc.) LET'S GET RID OF
THEM, PEACE/COOPERATION (mutexes and cond.var(s)) RULE!
Agreed? ;-)
> > > [e.g., you don't need an external mutex with events].
> >
> > But you DO need "internal mutex"... to communicate the
> > state of shared "flag" (and associated application shared
> > data) among different threads (processors -- hint: "memory
> > sync".), to begin with; apart from "blocking" - with NO
> > clear separation between "locking" and "waiting" (see POSIX
> > threads Rationale), etc.
>
> Not necessarily. Events may be used to communicate things without any
> synchronization at all [OK, events _are_ a synchronization mechanism, but
> here I'm using the word in the narrow sense of having two or more threads
> interlock]. A simple example that I see every other day in the real world
> software: a thread that does things periodically. That thread must terminate
> upon some condition. The archetypical Win32 idiom for that is an event for
> "time to quit" and WaitForSingleObject() with a timeout for periodical
> wake-up. You could do the same with a condvar, but it takes another boolean
> variable, to say nothing of the mandatory ex_mutex. Events are conceptually
> simpler in _this_ case.
They are not "simpler in _this_ case" they are SUPERFICIAL
"in _this_ case". You neither need "event"-monitors nor
anything else like that. You should just "sleep" and simply
use THREAD-CANCELATION (NOT [annotations]TerminateThread)
"in _this_ case" (periodical wake-up with "time to quit").
> > Oh <sigh>... My, *WaitForMultiple*... Don't get/provoke
> > me on this, please. FYI:
> >
> >
> http://groups.google.com/groups?selm=slrn7hiau9.1q3.kaz%40ashi.FootPrints.ne
> t
> > (*HTH*, I especially like "...president of the United States." bit ;-))
>
> Good points, but not very convincing. For the one place of sleeping, this is
> exactly how NT kernel is implemented, but that place may have a variable
> length list of waitable dispatcher objects, and when one of them becomes
> signaled it is quite simple for the scheduler to wake the thread if it is an
> "any" wait, or traverse the whole list it is the an "all" wait. When I say
> "variable length" it is indeed so; the 64 objects limitation is artificial
> and probably comes from the inability to communicate larger numbers in the
> status code returned by the native API, which is [yes!] silly.
[no!] *brain-damaged*. ooops. sorry. just can't
resist but won't repeat it here (as promised ;-)).
> For the starvation, a nice try, but if you're using that, you should think
> of that, right?
Right. And what are you going to do with it?
> Not scaling is hardly an issue, as there is seldom a need to wait for more
> than just a handful [fixed, at that] of objects.
Well, "seldom need"-yes-or-no aside, for example:
http://groups.google.com/groups?threadm=fFcE8.15279%24bV3.658502%40news0.telusplanet.net
(Subject: very funny ...WaitForMultipleObject failed)
> Then there are many things ultimately saying "not portable", but if I don't
> care about that?
Why don't you care about how big is the market you could
sell your stuff? BTW, ever heard of NT's POSIX.1 subsystem
("in addition" to [annotations]Win32-thing)? Funny story...
Some time ago (on comp.std.c++) I've mentioned (posted) a
link to one MSDN (pretty old one) article on this topic in
the connection with the ongoing MS-antitrust case... guess
what? that article, which for years stayed peacefully as
part of MSDN-LIB (online, CDs, subscriptions - I was
"universal" for the long time until recently) WAS PROMPTLY
ELIMINATED BY MS-FOLKS. Fascinating. ;-)
They "forgot to kill" the "support page" that reference
that eliminated article, however:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q149902
("Limitations of POSIX Applications on Windows NT (Q149902)")
Well, for more details on this (MS-POSIX, I mean),
please see the attached "RE: POSIX.C++" e-mails...
> The advice to make an aggregate object is good [I anticipated that] but that
> is not always possible. Say, if you're doing NT-style async IO, you can't.
> If you just using somebody else's code which gives you the handle to wait
> on, you can't. If you're waiting on an object exported by a separate process
> [by its name], you can't. Granted it may be possible if the design of all
> the components takes that into the account,
That is the point.
> but we are being realistic here, right?
Right! So, the outcome is: DON'T USE EVENTS/SEMAS,
unless you just absolutely can't avoid them. Right?
> > Uhmm. What do you mean? If "sources do not cooperate"
> > they simply AREN'T threads -- what are you talking
> > about?
>
> Sources of events. Code the sets/resets them. See the previous paragraph.
See my previous paragraph.
> > Well, MS-auto-reset event is also known to ABM-world as BIN.SEMA
> > (pulsing aside), to begin with. And, semas (and MS-ones with that
> > silly/brain-damaged "max" count, especially)
>
> Well. Then just use 0x7fffffff for that.
Yeah, that's NOT bad. But the problem is that I've "seen" code
that tries to EXPLOIT that "max"-thing -- a lot of folks are
just fooled by it, AFAICT. THAT's the real problem, IMHO.
> > aren't really much
> > better than events *for shared memory (with it, I mean) cooperative
> > sync.protocols and threading: "medium to fine-grained structuring
> > mechanism for parallelism in an application" (signals/interrupts
> > aside)*. Read the POSIX threads Rationale on semas, please (I've
> > already posted the {indirect} link somewhere in this thread, and,
> > BTW, that old DEC-SRC research paper also mentioned it).
>
> I've read that but events already are more than I can handle in this
> discussion [short of time, sorry].
Well, "OK". ;-)
> > > [having
> > > diagonally scanned the long article you referenced yesterday, I can tell
> > > you know that].
> >
> > I'm not sure what you imply by "that", really.
>
> Only that you know that events may be avoided for condvars implementation,
> thus eliminating another reason to compare them.
Well, given that SignalObjectAndWait simply does NOT
{practically} work, you need something to block/unblock
threads in order to emulate cond.vars on Win32 (running
as a client, see below). AFAICT, you could only use
events or semas which is pretty much the same stuff.
regards,
alexander.
http://www.opengroup.org/austin/lists.html
-----
To: austin-...@opengroup.org
cc:
Subject: RE: POSIX.C++
> Try reading http://www.microsoft.com/windows/sfu
My reply can be found on the austin-offtopic-l reflector
(there is "List archiver/reposter browser" interface for
members... if you are NOT *subscribed* to it, I mean).
regards,
alexander.
-----
To: austin-o...@opengroup.org
cc:
Subject: RE: POSIX.C++
> Try reading http://www.microsoft.com/windows/sfu
Thanks. You probably mean that "sfuposix" bit...
"....
The INTERIX environment subsystem replaces the original
Microsoft POSIX subsystem with something far more functional
and robust, useable, and integrated with the rest of the NT
environment.
...."
Last question/remark/plea: would it really be the entirely BAD
idea to bring that old article about "original Microsoft POSIX
subsystem" back to the old URL/place (that *WAS* working until
recently) since it is still (at least up to now, I've just re-
checked that support page) referenced on your support site...
and just add the link (above) pointing the existence of
"something far more functional and robust, useable, and
integrated with the rest of the NT environment" to that
updated "msdn_posix.asp" web page?
TIA.
regards,
alexander.
"Jason Zions" <{censored}@microsoft.com> on 05/16/2002 07:31:37 PM
Please respond to "Jason Zions" <{censored}@microsoft.com>
To: Alexander Terekhov/Germany/IBM@IBMDE, <austin-...@opengroup.org>
cc:
Subject: RE: POSIX.C++
Try reading http://www.microsoft.com/windows/sfu
-----Original Message-----
From: Alexander Terekhov [mailto:{censored}]
Sent: Thursday, May 16, 2002 5:43 AM
To: austin-...@opengroup.org
Subject: Re: POSIX.C++
> a bit and take over all your former colleges from WG21 *plus
^^^^^^^^
err. "colleagues" (aka: sort-of-"phonetic"-Russian-
in-Latin: TOVARISH/DRUG, but plural ;-)) sorry.
> Please do a search on "PACE", I've posted a couple of
> rather interesting links and quotes to comp.std.c++ some
> time ago; don't have a link, sorry.
got it:
http://groups.google.com/groups?selm=3C8FCC2F.9B4B1AAB%40web.de
(Subject: Re: C++ concurrency library feature-set)
"....
http://www.cs.wustl.edu/~luther/PACE/PACE-abstract.html
"PACE was born to abstract support for current and additional
non-POSIX platforms away from ACE, thus, becoming an API for
ACE developers to write to."
http://www.cs.wustl.edu/~luther/PACE/Introduction/begin.html
"This idea quickly developed into the broader concept
that the POSIX interface library could actually replace
the ACE_OS layer in the feature laden ACE framework
library and has since grown or will grow to include
platforms such as Win32 and VXWorks (which lack true
POSIX compliance)."
"As you can see, this creates a benefit for ACE,
namely, PosixACE (PACE) becomes a formal starting
point to begin reducing the complexity and interdependence
problems that had creeped into ACE over the past 5 years."
<wink>! <wink>!! <wink>!!!
A few more "random" refs:
...."
BTW, [and sorry for somewhat off-topic stuff] in regards
to Win32-"(which lack true POSIX compliance)"...
Does anyone from Microsoft here know what happened with
that nice article about WinNT's *POSIX subsystem* and
POSIX standardization process (bits like "POSIX" != "UNIX",
etc.)... after I've posted the link pointing to it (with a
few annotations) to comp.std.c++:
http://groups.google.com/groups?selm=3CC15F8E.7D694C67%40web.de
(Subject: Re: Boost.Threads and Dinkum CoreX)
The "old" URL:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwbgen/html/msdn_posix.asp
yields "Page Cannot Be Found"... search does NOT
help either.
Well, I still have that article on one of my old MSDN-
universal-subscriber's CDs (October 2001, Library, IIRC),
but the problem is that my @web.de address got pretty much
"bombarded"-to-death by various folks asking for it and
demanding explanations (why the posted link does NOT work;
did it ever work or am I just "trolling"; etc. etc.).
Folks ([MSFT]), given that you DO *still reference that
article on your support site*, please-please, bring it back!
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q149902
"....
REFERENCES
MSDN Development Library,
"Understanding Windows NT POSIX Compatibility", by Ray Cort. "
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Thank you in advance.
regards,
alexander.
Alexander Terekhov/Germany/IBM@IBMDE on 05/16/2002 12:36:41 PM
Please respond to Alexander Terekhov/Germany/IBM@IBMDE
To: austin-...@opengroup.org
cc:
Subject: Re: POSIX.C++
> I'm very interested in this discussion as well (if only because I was
> recently appointed co-liaison from WG21 to WG15 ;-) ).
Exciting/Promising! Good news!! My "advice"/wish: now conspire a bit and
take over all your former colleges from WG21 *plus WG14-folks* merging C
and C++ languages/standards (C++ would become "just-CORE"-lang-extension)
and all POSIX standard OS-extensions-options into *the single POSIX.1++
standard providing THE standard language AND OS bindings for BOTH C AND
C++ CORES*! We may even call it then "Java.2K" or simply "the right Java"
(marketing slogans like ".Net"-something aside)! ;-)
> Besides www.boost.org, the ACE project at
> http://www.cs.wustl.edu/~schmidt/ACE-overview.html shows one effort
Please do a search on "PACE", I've posted a couple of
rather interesting links and quotes to comp.std.c++ some
time ago; don't have a link, sorry.
regards,
alexander.
Lois Goldthwaite <{censored}.com> on 05/16/2002 05:07:05 AM
Please respond to Lois Goldthwaite <{censored}.com>
To: austin-...@opengroup.org
cc:
Subject: Re: POSIX.C++
I'm very interested in this discussion as well (if only because I was
recently appointed co-liaison from WG21 to WG15 ;-) ).
Besides www.boost.org, the ACE project at
http://www.cs.wustl.edu/~schmidt/ACE-overview.html shows one effort towards
mapping the APIs portably into C++, and specifically is concerned with
real-time operating systems. If you follow the link to the source tree at
http://www.cs.wustl.edu/~schmidt/ACE-directory.html,
there is another link to a Rational Rose model of the ACE classes.
The C++ Toolkits formerly from Objectspace (now from
www.recursionsw.com) provided a set of very usable C++ wrappers for OS
primitives, although no one ever formally modeled them in UML.
I also found this reference, though it's not about POSIX per se: MAST
Real-Time View: A Graphic UML Tool for Modeling Object-Oriented Real-Time
Systems.
J.M.Medina, M. González Harbour, and J.M.Drake.
Proceedings of the 22nd IEEE Real-Time Systems Symposium (RTSS 2001),
London, UK, IEEE Computer Society
Press, pp. 245-256, December 2001.
http://ctrpc17.ctr.unican.es/publications/jlm-mgh-jmd-2001c.html
Lois
Lonnie VanZandt wrote:
>
> Please add me to any discussion list you encounter on this topic. I am
> attempting model POSIX RT APIs in UML and an object-based API would be
> so much simpler to model because the class structure would already be
> specified. (If anyone has already encountered a POSIX RT UML model,
> save me the pain and point me to it.)
>
> Lonnie L. VanZandt
> {sig.censored}
>
> -----Original Message-----
> From: Daniel Miller [mailto:{censored}]
> Sent: Wednesday, May 15, 2002 10:16 AM
> To: austin-...@opengroup.org
> Subject: POSIX.C++
>
> Is there any effort (either official or unofficial) related to a
> C++ binding for the POSIX.1-series---especially the real-time
> extensions? If so, I would
> like to contact that subcommunity (or subcommunities, if there would
> happen to
> be more than one competing [would-be-]proposal).
>
> Such a C++ binding would complement the existing C binding inherent
> throughout the POSIX.1-series, the Ada binding in POSIX.5 and the
> Fortran binding in POSIX.9.
>
> {sig.censored}
[...]
> There are still some things even after all these *decades* that the
> general-purpose/hosted software world can learn from the embedded
> real-time software world with respect to multithreaded software designs
> which we have pioneered & honed over many years.
> That is, only if you admit that we exist in the first place and have
> a multi-decade multithreaded knowledge-base built up in our sector of the
> industry.
I do admit that. However, I _was_ talking about a different sector. And you
have not so far told anything about "pioneering/not-pioneering" in _this_
sector. Standing on the shoulders is a good thing, but RTOS/embedded sector
is sufficiently isolated and even evolves differently from the sector of
general purpose OSes and applications. Even the author of this phrase
[standing on the shoulders etc] had about 30 years of conflict with the
folks who did the same thing slightly differently [about pioneering, in
particular]. I do not think it is any different these days. It takes more
than a couple years for ideas to propagate, be well understood and well
established... more so when coming from a different "sector".
S
[...]
> Does this mean that you now AGREE that condvars ARE
> much BETTER than {annotations} events and semaphores?
I certainly do not rule them out. However, I do believe that in day-to-day
situations events may reasonably be used. Finally, given that condvars are
not natively supported by Win32, the whole topic is moot...
OK, when it comes to delivering an "edge" type signal to multiple waiters,
condvars are great because this is precisely what they are designed for. In
other cases...
[...]
> They are not "simpler in _this_ case" they are SUPERFICIAL
> "in _this_ case". You neither need "event"-monitors nor
> anything else like that. You should just "sleep" and simply
> use THREAD-CANCELATION (NOT [annotations]TerminateThread)
> "in _this_ case" (periodical wake-up with "time to quit").
Perhaps. I, however, like to give threads an opportunity to do whatever they
want and just signal "time to terminate". When you have dozens of such
threads it is much simpler to set just one event.
> > For the starvation, a nice try, but if you're using that, you should
> > think of that, right?
>
> Right. And what are you going to do with it?
Many things. First, I do not remember exactly, but NT may already give
priority to the stuff which goes early in the objects array. Second, you may
remove objects temporarily if they fire too often. Third, you may have a
dedicated thread for frequent objects. Fourth, you might take some design
decision that eliminates that sort of starving in the first place.
[...]
>
http://groups.google.com/groups?threadm=fFcE8.15279%24bV3.658502%40news0.te
lusplanet.net
> (Subject: very funny ...WaitForMultipleObject failed)
Well, without knowing what the intent was, it's hard to suggest anything.
However, starting 100 applications and then waiting on all of them is
already sort of strange.
> Why don't you care about how big is the market you could
> sell your stuff?
I _personally_ and _now_ do not care. I work in a company that makes some
security products for NT, not even generic Win32. We're unlikely to ever
want to do anything non-NT, and even if we do, doing synchronization in a
portable way is the least concern for us :-)
> BTW, ever heard of NT's POSIX.1 subsystem
> ("in addition" to [annotations]Win32-thing)? Funny story...
Yeah, but, IIRC, it was _only_ because USA govt systems have/had to be
_some_ POSIX compliant, so MS just did that to sell NT. Nobody cared that it
was merely hot air, not even the USA govt :-)
[...]
> > Say, if you're doing NT-style async IO, you can't.
> > If you're waiting on an object exported by a separate process
> > [by its name], you can't.
[...]
> Right! So, the outcome is: DON'T USE EVENTS/SEMAS,
> unless you just absolutely can't avoid them. Right?
No. I said about async IO [without completion ports]. I said about objects
exported by their name. Finaly, I said about WaitForMultipleObject() and not
events or semaphores.
> > Well. Then just use 0x7fffffff for that.
>
> Yeah, that's NOT bad. But the problem is that I've "seen" code
> that tries to EXPLOIT that "max"-thing -- a lot of folks are
> just fooled by it, AFAICT. THAT's the real problem, IMHO.
I don't know. Perhaps I'm just too smart so it has never occured to me :-) I
don't care, really.
S
[...]
> > until 1985
[...]
> http://groups.google.com/groups?selm=3BE7ABD3.6303D8E1%40web.de
The article by Hoar is concerned with mutexes [called monitors there] and
single-signal condvars which are simpler than multi-signal condvars. In fact
they can trivially be implemented by using a Win32 mutex and a semaphore [as
the article later on goes demonstrating]. Most of condvars complexity
[implementation-wise in Win32] is related to delivering the signal to
multiple waiters, especially if one wants to be efficient at that.
The second article I did not have access to.
The third article is dated 1987.
The fourth item [the condvars CVS log] has the first entry in 1998.
Then there is link to an article of yours, which is 2001.
The final link leads to a site which I cannot review in its entirety :-)
Two other links that you referenced may contain some insight but they are
irrelevant to the "until 1985" thing, as all of the previous except the
first one.
> Slava, do you still have any more questions/remarks?
Questions I did not have, excluding the rhetorical ones. As for the remarks,
I had a remark which has been ignored by everybody so far:
[begin remark]
I can take back the word "pioneer" if you are unhappy about that. But in
mainstream application programming threads had little appearance, if any,
before Win32. Most of the RDBMS on UNIX and VMS normally had multiple
processes and not multiple threads well into 90s. Same applies to other
types of network servers. I hear it was different on mainframes, though.
[end remark]
S
[...]
> FWIW, I work for IBM (Germany) and would consider "work" for
> Microsoft as a BAD THING with respect to "better sleep". ;-)
If nobody worked for MS, they would not exists. And we would not have this
discussion, which might be boring.
S
> The article by Hoar is concerned with mutexes [called monitors there] and
> single-signal condvars which are simpler than multi-signal condvars.
I think you have mis-read the article by Hoar. His monitor is not the
same as a mutex.
"The procedures of a monitor are common to all running programs, in the
sense that any program may at any time attempt to call such a procedure.
However, it is essential that only one program at a time actually
succeed in entering a monitor procedure, and any subsequent call must be
held up until the previous call has been completed. Otherwise, if two
procedure bodies were in simulatenous execution, the effects on the
local variables of the monitor could be chaotic. The procedures local to
a monitor should not access any nonlocal variables other than those
local to the same monitor, and these variables of the monitor should be
inaccessible from outside the monitor. If these restrictions are
imposed, it is possible to guarantee against certain of the more obscure
forms of time-dependent coding error; and this guarantee could be
underwritten hy a visual scan of the text of the program, which coulcl
readily be automated in a compiler."
The monitor described by Hoar is fully implemented by protected
procedures in the Ada language.
"In many cases, there may be more than one reason for waiting, and these
need to be distinguished by both the waiting and the signalling
operation. We therefore introduce a new type of "variable" known as a
"condition"; and the writer of a monitor should declare a variable of
type condition for each reason why a program might have to wait."
Condition variables, then, are described by Hoar as being part
of a monitor. Note that condition variables are used to provide
specialized access restraints to a monitor. They are not used in
place of a monitor.
Monitors with condition variables are fully implemented by protected
entries in the Ada language.
Ada adds one more feature to protected objects. Protected functions
allow concurrent reads of a monitor. Protected procedures and protected
entries provide exclusive access to a monitor, which Ada calls a
protected object.
Following is an example of a monitor implemented as a protected
objec in Ada. The example defines a circular queue of integers.
Ada requires the definition of an interface or specification
separate from the implementation of the actual methods.
protected object Queue is
procedure Clear;
entry Enqueue(Item : in Integer);
entry Dequeue(Itme : out Integer);
function Count return Natural;
private
Buffer : array(0..9) of Integer;
Put_Index : Natural := 0;
Get_Index : Natural := 0;
Num_Items : Natural := 0;
end Queue;
protected body Queue is
procedure Clear is
begin
Num_Items := 0;
Get_Index := 0;
Put_Index := 0;
end Clear;
entry Enqueue(Item : in Integer) when Num_Items < Buffer'Length is
begin
Buffer(Put_Index) := Item;
Num_Items := Num_Items + 1;
Put_Index := Put_Index + 1 mod Buffer'Length;
end Enqueue;
entry Dequeue(Item : out Integer) when Num_Items > 0 is
begin
Item := Buffer(Get_Index);
Num_Items := Num_Items - 1;
Get_Index := Get_Index + 1 mod Buffer'Length;
end Dequeue;
function Count return Natural is
begin
return Num_Items;
end Count;
end Queue;
Note that the procedure "Clear" can be executed unconditionally.
Tasks (threads) calling a procedure will be suspended while any
other task is executing a procedure, entry, or function.
The entry "Enqueue" can only be executed when Num_Items < Buffer'Length.
If the buffer is full the calling task is placed in an
entry queue and suspended until the number of items in the buffer
decreases.
The entry "Dequeue" can only be executed whe Num_Items > 0.
A task calling an entry will be suspended while any other task
is executing a procedure, entry, or funciton.
The function "Count" can be called by many tasks simultaneously.
Tasks calling the function will suspend while any other task is
executing a procedure or entry.
Jim Rogers
Alexander> "Michael J. Saletnik" wrote:
Alexander> [...]
>> Having participated in an implementation of condition variables on
>> Win32, it was very difficult to get right.
Alexander> Could you please show us your impl (it is fairly simple
Alexander> thing with thread-specific "blockers"/explicitly managed
Alexander> queue)?
I wonder what was the rationale to do it the complicated way. I mean
the current pthreads-win32 condvar implementation is difficult to
grasp, and uses several OS objects for one condvar instance (where
"normal" Unix condvars usually do not need any kernel resources). The
only reason I can think of is that you would be leaking the "blocker"
object (an event, I assume) when you don't own thread creation and
cleanup. But when you are using pthreads-win32 you do own these. Or am
I wrong?
Joerg
For the pthreads-win32 developers, or for the software I worked on?
What do you mean by "the complicated way"? I'm not sure what you're
asking me?
--
{michael}
http://groups.google.com/groups?threadm=3BC4CE86.4A42A238%40web.de
"....
> You can use a semaphore as a non owned exclusion object.
> Set the maximum count to 1.
I'm just curious whether anyone has an example of *correct* code
that shows how to exploit that "LONG lMaximumCount" ("The count
can never be less than zero or greater than the value specified
in the lMaximumCount parameter)?
...." <see the entire thread>
> I don't care, really.
That's BAD, IMHO.
regards,
alexander.
That's WRONG.
> and single-signal condvars which are simpler than multi-signal condvars.
You mean MODERN POSIX Threads condvars? *THE
ORIGINAL/ARCHAIC*-ones are just less efficient,
to begin with (AFAICT).
[...]
> The second article I did not have access to.
You mean:
http://www.acm.org/pubs/citations/journals/surveys/1973-5-4/p223-hansen
("Concurrent Programming Concepts")
<?>
Here is an "event" (Hansen analyzed "MS-pulse"
ones ;-)) related quote from that paper:
"....
We must therefore conclude that event
variables of the previous type are impracti-
cal for system design. The effect of an inter-
action between two processes must be inde-
pendent of the speed at which it is carried
out. A far more attractive synchronizing tool,
the semaphore, was invented by Dijkstra in
1965. [4, 5]..."
And... few quotes on semaphores from that
(*December 1973*) paper can be found here:
http://groups.google.com/groups?selm=3BC83D15.46FA3731%40web.de
And, finaly, Hansen wrote in that paper:
"It has therefore recently been suggested that
one should combine a shared variable and the
possible operations on it in a single, syntactic
construct called a monitor [1, 10, 11]. It is,
however, too early to speculate about what this
approach may lead to."
But, I guess, *NOW*... we CAN "speculate
about what this approach may lead to"...
*POSIX Threads condvars* <!>
Or am I missing something? ;-)
regards,
alexander.
Even if it is not a mutex, it is or it _contains_ a mutual exclusion
mechanism because " [...] it is essential that only one program at a time
actually succeed in entering a monitor procedure, and any subsequent call
must be held up until the previous call has been completed". If we focus
on the exclusion mechanism _itself_, I fail to see how it is different
from what we call mutex these days.
S
"academic exercise" was the rationale! ;-)
Seriously, explicitly managed queue approach (like ZThreads's
one, presuming it's correctly implemented there ;-)) requires
making scheduling decisions -- wakeup order; think of priorities,
etc.
> I mean
> the current pthreads-win32 condvar implementation is difficult to
> grasp, and uses several OS objects for one condvar instance (where
> "normal" Unix condvars usually do not need any kernel resources).
It depends, I guess.
> The
> only reason I can think of is that you would be leaking the "blocker"
> object (an event, I assume) when you don't own thread creation and
> cleanup.
Well, it could be done even w/o owning thread creation and
cleanup -- just thread-specific events/semas (one would need
"correctly working" cleanup of thread-specific data, though;
that's somewhat a real challenge under brain-damaged win32-
native--without-pthreads-win32-I-mean ;-)).
> But when you are using pthreads-win32 you do own these.
> Or am I wrong?
Well, the pthreads-win32 CV-impl. could be simplified quite
considerably... As another "academic exercise" it tries to
fight (avoid generating of) spurious wakeups due to timeouts
and cancel; That's absolutely NOT required by the POSIX Threads
standard (*very wise decision*, given the presence of
"application"-induced "spurious" wakeups; and the simplicity/
robustness of while or do "waiting" loops), and given that extra
complexity and bookkeeping it takes to fight them (in the case
of pthreads-win32, I mean), is just counter productive,
I guess. ;-)
regards,
alexander.
[Win32 semaphore max count]
> > I don't care, really.
>
> That's BAD, IMHO.
Why? You can avoid using the max. count. Then, if you _can_ find any utility
in that max count, you can use it. If you can _not_, you do not use it. Fair
gamble, is it not?
S
> > The article by Hoar is concerned with mutexes [called monitors there]
>
> That's WRONG.
I've replied to a similar comment already.
> You mean MODERN POSIX Threads condvars? *THE
> ORIGINAL/ARCHAIC*-ones are just less efficient,
> to begin with (AFAICT).
Yes to the question; the "new condvars" are not just more efficient: they
contain functionality not described by Hoar, signal broadcasting to be
precise. You of course can emulate the broadcast-type signal with "new
condvars" if that is what you mean by "less efficient".
> > The second article I did not have access to.
>
> You mean:
>
> http://www.acm.org/pubs/citations/journals/surveys/1973-5-4/p223-hansen
> ("Concurrent Programming Concepts")
Yes.
> Here is an "event" (Hansen analyzed "MS-pulse"
> ones ;-)) related quote from that paper:
A remark on style: given the year of publication, the "events" in question
can hardly be called "MS-pulse". That brilliant idea belongs to somebody
else. IIRC, this branch of the thread is devoted to "who pioneered what" so
let us be strict.
> "....
> We must therefore conclude that event
> variables of the previous type are impracti-
> cal for system design. The effect of an inter-
> action between two processes must be inde-
> pendent of the speed at which it is carried
> out."
Without reading the whole article it is hard to argue with that.
> "A far more attractive synchronizing tool,
> the semaphore, was invented by Dijkstra in
> 1965. [4, 5]..."
Which is a part of Win32.
[...]
> But, I guess, *NOW*... we CAN "speculate
> about what this approach may lead to"...
>
> *POSIX Threads condvars* <!>
Which does not necessarily mean it has led to _good_, which was probably the
author's concern. You're trying to position condvars as something ultimate
in synchronization, which they are simply not, one reason being their strict
serializing of threads being released from wait. Semaphores, say, do not
have this property. Events do not have that property either.
S
> Even if it is not a mutex, it is or it _contains_ a mutual exclusion
> mechanism because " [...] it is essential that only one program at a time
> actually succeed in entering a monitor procedure, and any subsequent call
> must be held up until the previous call has been completed". If we focus
> on the exclusion mechanism _itself_, I fail to see how it is different
> from what we call mutex these days.
I agree that it can be valuable to focus on mutual exclusion mechanisms.
However, comparing a monitor to a mutex is somewhat like comparing a
house to a door lock. If houses generally have door locks it still does
not make logical sense to say that a house is a door lock.
Hoar's monitor is a sophisticated object containing mutual exclusion
mechanisms. It also contains member methods and boundary conditions
for access to those methods. The boundary conditions work with the
mutual exclusion mechanisms, but are separate entities.
The purpose of a mutex is to prevent mutual access to an object.
The purpose of a monitor is to define a self-consistent shared
resource. The mutex is no more than the lock on the door of the
monitor. Note that the condition variable is a secondary lock
based upon the internal state of the monitor while the mutex is
a lock based upon the state of threads accessing the monitor. It
makes no sense to test the value of the condition variable until
you have acquired the mutex for the object.
Jim Rogers
> I agree that it can be valuable to focus on mutual exclusion mechanisms.
> However, comparing a monitor to a mutex is somewhat like comparing a
> house to a door lock. If houses generally have door locks it still does
> not make logical sense to say that a house is a door lock.
>
> Hoar's monitor is a sophisticated object containing mutual exclusion
> mechanisms. It also contains member methods and boundary conditions
> for access to those methods. The boundary conditions work with the
> mutual exclusion mechanisms, but are separate entities.
The problem is, in the sense as used by you, monitors cannot be compared to
anything, not even to other monitors [unless the other monitors have the
same "member methods" and "boundary conditions"]. The minimal common
property of monitors is mutual exclusion, the rest is arbitrary. Hoar is
explicit about that, c.f. his "simplest example of a monitor". This mutual
exclusion property is the primary property of monitors, used to define
monitors. This is the property that can be used to infer "X is a monitor",
and "Y is a monitor", and "X and Y belong to the same class of things".
Following this pattern, it is natural to compare mutexes to monitors.
S
By "less efficient" I mean NOT-designed-for-better-throughput[1],
to begin with.
> > > The second article I did not have access to.
> >
> > You mean:
> >
> > http://www.acm.org/pubs/citations/journals/surveys/1973-5-4/p223-hansen
> > ("Concurrent Programming Concepts")
>
> Yes.
>
> > Here is an "event" (Hansen analyzed "MS-pulse"
> > ones ;-)) related quote from that paper:
>
> A remark on style: given the year of publication, the "events" in question
> can hardly be called "MS-pulse". That brilliant idea belongs to somebody
> else.
Yep. But MS *DID* demonstrate the-brain-damage-principle-at-work
via adopting that "brilliant idea". Or am I just missing something?
> IIRC, this branch of the thread is devoted to "who pioneered what" so
> let us be strict.
>
> > "....
> > We must therefore conclude that event
> > variables of the previous type are impracti-
> > cal for system design. The effect of an inter-
> > action between two processes must be inde-
> > pendent of the speed at which it is carried
> > out."
>
> Without reading the whole article it is hard to argue with that.
Well, "oll korrect" ;-)
Perhaps the following quote could provide you MORE/SUFFICIENT
context (make it a little *easier* to argue, I mean ;-))?
"....
Another kind of timing signals, called events,
was used in early multiprogramming systems to
synchronize concurrent processes. When a process
decides to wait for an event, the execution of
its next operation is delayed until another process
causes the event. An event occurring at a time
when no processes are waiting for one has no effect.
....
The most important result of this analysis
is the general observation that mutual ex-
clusion of all operations on a shared variable
enables the programmer to analyze the pos
sible effects of a process interaction in finite,
sequential terms. For the special case of
event variables, we have also discovered
that the net effect of await and cause opera-
tions depends on the order in which these
operations are carried out. Or, to put it more
strongly: event operations force the pro-
grammer to be aware of the relative speeds
of the sending and receiving processes.
The programmer does not control the
order in which concurrent statements are
executed; he is therefore unable to predict
the effect of a process interaction revolving
events. In a real-time system, the program-
mer has essentially lost control of process
scheduling--he cannot define a process that
will schedule other processes in a predictable
manner. Event variables are only meaning-
ful to use when one can assume that a
process never is asked to carry out another
task until it has completed its previous task.
Although this assumption may be satisfied
in some applications, it will still complicate
programming tremendously if one depends
on it. The programmer must then be aware
of the relative speeds of processes under all
circumstances. If a multiprogramming sys-
tem is so large that no single person under-
stands its dynamic behavior in detail, the
individual programmer cannot make reliable
estimates of the relative speeds of processes
under all circumstances. In particular, it will
be an intolerable burden to verify that the
speed assumptions are uninfluenced by
modifications or extensions of a large sys-
tem.
We must therefore conclude that event
variables of the previous type are impracti-
cal for system design. The effect of an inter-
action between two processes must be inde-
pendent of the speed at which it is carried
out.
A far more attractive synchronizing tool,
the semaphore, was invented by Dijkstra in
1965. [4, 5] A semaphore is a variable used
to exchange timing signals among concurrent
processes by means of two operations, wait
and signal (originally called P and V)."
> > "A far more attractive synchronizing tool,
> > the semaphore, was invented by Dijkstra in
> > 1965. [4, 5]..."
>
> Which is a part of Win32.
And which is *NOT* a part of POSIX Threads,
for *really good reasons*... you just FAIL
to SEE, unfortunately. ;-(
> > But, I guess, *NOW*... we CAN "speculate
> > about what this approach may lead to"...
> >
> > *POSIX Threads condvars* <!>
>
> Which does not necessarily mean it has led to _good_,
No, it DOES.
> which was probably the
> author's concern. You're trying to position condvars as something ultimate
> in synchronization,
Yes, I do.
> which they are simply not,
Have you ever used them, to begin with?
> one reason being their strict
> serializing of threads being released from wait.
You mean reacquisition of the mutex being part of wakeup[2]?
Have you EVER used condvars? Have you ever tried to do
timed waits? How about cancel with some cleanup? For
all these things you need a mutex to do something useful;
"application"-induced "spurious" wakeups aside -- they
are handled just like implementation-induced one (think
of signals/interrupts breaking-out waiting threads for
awhile, for example) via rechecking the predicate under
mutex protection after wakeup. And there is also memory
sync./vibility protocol provide by the same mutex -- you
just canNOT avoid that "serializing of threads being
released from wait" NOT breaking the *usefulness (w.r.t.
their general purpose application) and superiority* of
condvars, AFAICT!
> Semaphores, say, do not have this property.
Internally, they DO.
> Events do not have that property either.
Internally, they DO.
Please see pseudo-events and semas I've already posted
somewhere in this thread.
Events and semas are just special-purpose,
rather restricted/narrow-minded, error prone
and pretty much USELESS (signals/interrupts/IPC
w.r.t. to semas aside) *MONITORS* with INTERNAL
mutex/shared data/predicate(s) and condvar(s)!
You might want to take a look at my recent
postings and links to the following c.p.t.
threads as well:
http://groups.google.com/groups?threadm=b9c563f9.0205071053.37baf3c2%40posting.google.com
http://groups.google.com/groups?threadm=3mhE8.15629%24bV3.677568%40news0.telusplanet.net
regards,
alexander.
[1] http://groups.google.com/groups?selm=31C00450.2781%40zko.dec.com
http://groups.google.com/groups?selm=31B80BB0.59E2%40zko.dec.com
(Subject: Re: pthread_cond_wait is unfair (POSIX threads))
[2]
http://groups.google.com/groups?selm=94a12t%24rmp%241%40nnrp1.deja.com
(Subject: pthread_cond_* implementation questions ;-))
"....
>Why does the specification define mutex ownership ("if each had called
>pthread_mutex_lock()") being a part of semantics for condition_wait??
That is how everyone expects mutexes and condition variables to
work. It is the way C. A. R. Hoare invented monitors and conditions
some thirty odd years ago ...."
http://www.opengroup.org/onlinepubs/007904975/functions/pthread_cond_wait.html
"....
Features of Mutexes and Condition Variables
It had been suggested that the mutex acquisition and release be
decoupled from condition wait. This was rejected because it is
the combined nature of the operation that, in fact, facilitates
realtime implementations. Those implementations can atomically
move a high-priority thread between the condition variable and
the mutex in a manner that is transparent to the caller. This
can prevent extra context switches and provide more deterministic
acquisition of a mutex when the waiting thread is signaled. Thus,
fairness and priority issues can be dealt with directly by the
scheduling discipline. Furthermore, the current condition wait
operation matches existing practice.
...."
> The problem is, in the sense as used by you, monitors cannot be compared to
> anything, not even to other monitors [unless the other monitors have the
> same "member methods" and "boundary conditions"]. The minimal common
> property of monitors is mutual exclusion, the rest is arbitrary. Hoar is
> explicit about that, c.f. his "simplest example of a monitor". This mutual
> exclusion property is the primary property of monitors, used to define
> monitors. This is the property that can be used to infer "X is a monitor",
> and "Y is a monitor", and "X and Y belong to the same class of things".
> Following this pattern, it is natural to compare mutexes to monitors.
Your logic is still faulty.
First you say that monitors cannot be compared to anything.
Next you reference a very simple example of a monitor and see that
one of its features is a mutex. Using this example you want to
compare all monitors to mutexes.
This makes no more sense than comparing all classes to integers
because a simple class could contain a single integer, or because
all data is stored in binary.
Your logic claims that if "X is a monitor" and "Y is a monitor"
"X and Y belong to the same class of things". That still does not
make any progress to the statement that a monitor is a mutex.
In fact, Hoar's simplest example is more than merely a mutex. It
is an object that employs a mutex. Again, you are still trying to
equate houses and locks simply because a house has a lock.
Jim Rogers
But why the hell should I or anyone else ALWAYS pay
the price/processing cycles of checking w.r.t. that
silly count on almost every operation, internally,
I mean?
> Then, if you _can_ find any utility
> in that max count, you can use it.
I CAN*NOT* FIND ANY (USEFUL) UTILITY FOR IT,
I'VE TRIED HARD.
Can you find it? I'd be quite interested and heck,
eagerly awaiting to be informed of it... just in
case you (or someone else) indeed succeed in that
quest-for-MS-semas-max-count-usefulness!!!
> If you can _not_, you do not use it.
Se my first paragraph.
> Fair gamble, is it not?
It is NOT. Here is (for example) the "fair gamble"/
reasonable design analyses and considerations, as
it seems to me:
http://groups.google.com/groups?selm=3C9F8A77.652ED604%40web.de
"....
> And, OK, one could deal with the naming issues. Documentation, though,
> would be easily misunderstood. (That MUST be a prime concern in the design
> of any interface.) And, in the end, what do you have? Every call site that
> requests upgrade MUST be able to handle either return, but there's no way
> to predict for sure whether any given call will succeed or "not quite
> succeed". Easy to misunderstand and misuse, tough to test. Bad combination.
>
> The query operation sounds like an invitation to even greater screwups, to
> me. More complication, harder to test... for very little added value.
Uhmm, NOT bad analysis, I guess. Thanks!"
Well, just try to apply this "method" to the MS-sema's MAX
count... I'd be quite interested to see the outcome... ;-)
regards,
alexander.
[...]
> Yep. But MS *DID* demonstrate the-brain-damage-principle-at-work
> via adopting that "brilliant idea". Or am I just missing something?
Here goes you promise. Anyway, MS demonstrating or not, it is simply
incorrect to call events and pulsing thereof an MS invention, or infer that
by attaching some prefixes or suffixes.
[...]
> Event variables are only meaning-
> ful to use when one can assume that a
> process never is asked to carry out another
> task until it has completed its previous task.
What is that? No less than saying "they can indeed be useful sometimes."
> Although this assumption may be satisfied
> in some applications, it will still complicate
> programming tremendously if one depends
> on it.
That is jumping to conclusions. It _may_ complicate.
[...]
> > > "A far more attractive synchronizing tool,
> > > the semaphore, was invented by Dijkstra in
> > > 1965. [4, 5]..."
> >
> > Which is a part of Win32.
>
> And which is *NOT* a part of POSIX Threads,
> for *really good reasons*... you just FAIL
> to SEE, unfortunately. ;-(
Mutexes, semaphores and events are inherently more primitive objects than
condvars. They are inherently faster and have less overhead than condvars.
At least for these reasons they have a value. More on that below.
I can accept the opposite view that condvars and monitors are more primitive
and more generic, but at cost of the obligatory _application_induced_
lock/unlock requests.
> > Which does not necessarily mean it has led to _good_,
>
> No, it DOES.
How authoritative, that. Try adding something like "methinks" here and
there.
> > which they are simply not,
>
> Have you ever used them, to begin with?
A couple of times. I have especially bad memories of Java monitors which are
the same thing with some [supposed] syntactic sugar [which turns out true
nightmare; although I don't use Java much so I may be just biased]. I had
once to investigate why a certain Java application scaled poorly, if at all,
on some four-way server. Eventually I found it was due to excessive
serialization in the monitors. Originally I did not realize it was a
property of monitors. So I created another sync object with semantics of
Java monitors, with native methods, using some condvars implementation
[sorry, I do not remember what it was; it may very well have been one of
early pthreads implementations] as a reference. It did not help. I tried to
recode the thing when I finally realized that problem was fundamental. I
proposed another sync paradigm and the problem disappeared. That was a few
years ago. There were a few other cases, but the one I just described is the
one I remember so well.
> You mean reacquisition of the mutex being part of wakeup[2]?
Yes; besides, the implementation of condvars that you pointed me to a few
days ago contains another mutex or semaphore wait _apart_ from ex_mutex.
> Have you EVER used condvars? Have you ever tried to do
> timed waits? How about cancel with some cleanup? For
> all these things you need a mutex to do something useful;
> "application"-induced "spurious" wakeups aside -- they
> are handled just like implementation-induced one (think
> of signals/interrupts breaking-out waiting threads for
> awhile, for example) via rechecking the predicate under
> mutex protection after wakeup. And there is also memory
> sync./vibility protocol provide by the same mutex -- you
> just canNOT avoid that "serializing of threads being
> released from wait" NOT breaking the *usefulness (w.r.t.
> their general purpose application) and superiority* of
> condvars, AFAICT!
You can. The threads being released from the wait may perform some
"read-only" operation that does not require any interlocking. Or they do
some limited updates which can be performed by using hardware lock-modify
instructions.
> > Semaphores, say, do not have this property.
>
> Internally, they DO.
It is inside the scheduler and it does not involve an _explicit_ request
from application [after some arbitrary time]. Much less overhead, far more
parallel. User-mode implementations of condvars are especially bad because
they may _induce_ unnecessary context switches if the OS does priority
boosts to long waiting threads.
> > Events do not have that property either.
>
> Internally, they DO.
Same thing.
S
> Your logic is still faulty.
>
> First you say that monitors cannot be compared to anything.
No. I say that _according_to_you_ they cannot be compared to anything. I
said:
[begin quote]
The problem is, in the sense as used by you, monitors cannot be compared to
anything, not even to other monitors [unless the other monitors have the
same "member methods" and "boundary conditions"].
[end quote]
I certainly do not share this opinion. I do not compare houses to houses. I
can compare walls to walls and locks to locks. I can say that "the lock of
this house is completely similar to the lock of that house, which is in turn
similar to the lock that I saw on sales last week".
> Next you reference a very simple example of a monitor and see that
> one of its features is a mutex. Using this example you want to
> compare all monitors to mutexes.
It was not "next". Next was a statement that mutual exclusion is the
_minimal_ common property of monitors. Next to that next was indeed a
reference to the original text that confirms that "minimality" [Hoar used
the word "simplest"].
> This makes no more sense than comparing all classes to integers
> because a simple class could contain a single integer, or because
> all data is stored in binary.
If you define classes of category X as classes _necessarily_ containing an
integer, and having some _optional_ properties, then we can compare classes
of category X to integers. There is an isomorphism between integers and
classes that contain an integer _only_.
> Your logic claims that if "X is a monitor" and "Y is a monitor"
> "X and Y belong to the same class of things". That still does not
> make any progress to the statement that a monitor is a mutex.
Monitor is a mutex plus some. In this thread we are comparing
synchronization mechanisms. Other properties of monitors are not necessarily
related to synchronization. Unless a monitor contains any other
synchronization-related methods [as in condvars], it is completely similar a
mutex.
S
Alexander> Joerg Faschingbauer wrote:
>>
>> >>>>> "Alexander" == Alexander Terekhov <tere...@web.de> writes:
>>
Alexander> "Michael J. Saletnik" wrote:
Alexander> [...]
>> >> Having participated in an implementation of condition variables on
>> >> Win32, it was very difficult to get right.
>>
Alexander> Could you please show us your impl (it is fairly simple
Alexander> thing with thread-specific "blockers"/explicitly managed
Alexander> queue)?
>>
>> I wonder what was the rationale to do it the complicated way.
Alexander> "academic exercise" was the rationale! ;-)
Alexander> Seriously, explicitly managed queue approach (like ZThreads's
Alexander> one, presuming it's correctly implemented there ;-)) requires
Alexander> making scheduling decisions -- wakeup order; think of priorities,
Alexander> etc.
You don't have to with the current implementation?
>> I mean
>> the current pthreads-win32 condvar implementation is difficult to
>> grasp, and uses several OS objects for one condvar instance (where
>> "normal" Unix condvars usually do not need any kernel resources).
Alexander> It depends, I guess.
Yeah, as always. The LinxThreads implementation looks reasonable
however, and I don't think others have a real need to do it
differently (except for the process shared things, of course).
>> The
>> only reason I can think of is that you would be leaking the "blocker"
>> object (an event, I assume) when you don't own thread creation and
>> cleanup.
Alexander> Well, it could be done even w/o owning thread creation and
Alexander> cleanup -- just thread-specific events/semas (one would need
Alexander> "correctly working" cleanup of thread-specific data, though;
Alexander> that's somewhat a real challenge under brain-damaged win32-
Alexander> native--without-pthreads-win32-I-mean ;-)).
Yes, certain things are a major pain in the ass there.
>> But when you are using pthreads-win32 you do own these.
>> Or am I wrong?
Alexander> Well, the pthreads-win32 CV-impl. could be simplified quite
Alexander> considerably... As another "academic exercise" it tries to
Alexander> fight (avoid generating of) spurious wakeups due to timeouts
Alexander> and cancel; That's absolutely NOT required by the POSIX Threads
Alexander> standard (*very wise decision*, given the presence of
Alexander> "application"-induced "spurious" wakeups; and the simplicity/
Alexander> robustness of while or do "waiting" loops), and given that extra
Alexander> complexity and bookkeeping it takes to fight them (in the case
Alexander> of pthreads-win32, I mean), is just counter productive,
Alexander> I guess. ;-)
I see the problem. But aren't these wakeups negligible? I believe that
applications that use timeout and cancel not use them in tight loops.
Joerg
Michael> Joerg Faschingbauer <jfa...@localhost.localdomain> writes:
>> I wonder what was the rationale to do it the complicated way. I mean
Michael> For the pthreads-win32 developers, or for the software I worked on?
Michael> What do you mean by "the complicated way"? I'm not sure what you're
Michael> asking me?
(Sorry, I didn't ask you. This was a reply to a post of Alexander
Terekhov from comp.programming.threads. Maybe we shouldn't be
crossposting this much.)
With "the complicated way" I meant that I don't understand it :-)
Joerg
Current impl simply posts/unlocks "queue-sema",
see the pseudo-code below.
[...]
> Alexander> Well, the pthreads-win32 CV-impl. could be simplified quite
> Alexander> considerably... As another "academic exercise" it tries to
> Alexander> fight (avoid generating of) spurious wakeups due to timeouts
> Alexander> and cancel; That's absolutely NOT required by the POSIX Threads
> Alexander> standard (*very wise decision*, given the presence of
> Alexander> "application"-induced "spurious" wakeups; and the simplicity/
> Alexander> robustness of while or do "waiting" loops), and given that extra
> Alexander> complexity and bookkeeping it takes to fight them (in the case
> Alexander> of pthreads-win32, I mean), is just counter productive,
> Alexander> I guess. ;-)
>
> I see the problem. But aren't these wakeups negligible? I believe that
> applications that use timeout and cancel not use them in tight loops.
Yep. That entire spurious-wakeup-suppression-stuff
COULD and probably SHOULD be removed completely! ;-)
regards,
alexander.
* given:
* semBlockLock - bin.semaphore
* semBlockQueue - semaphore
* mtxExternal - mutex or CS
* mtxUnblockLock - mutex or CS
* nWaitersGone - int
* nWaitersBlocked - int
* nWaitersToUnblock - int
*
* wait( timeout ) {
*
* [auto: register int result ] // error checking omitted
* [auto: register int nSignalsWasLeft ]
* [auto: register int nWaitersWasGone ]
*
* sem_wait( semBlockLock );
* nWaitersBlocked++;
* sem_post( semBlockLock );
*
* unlock( mtxExternal );
* bTimedOut = sem_wait( semBlockQueue,timeout );
*
* lock( mtxUnblockLock );
* if ( 0 != (nSignalsWasLeft = nWaitersToUnblock) ) {
* if ( bTimeout ) { // timeout (or canceled)
* if ( 0 != nWaitersBlocked ) {
* nWaitersBlocked--;
* }
* else {
* nWaitersGone++; // count spurious wakeups.
* }
* }
* if ( 0 == --nWaitersToUnblock ) {
* if ( 0 != nWaitersBlocked ) {
* sem_post( semBlockLock ); // open the gate.
* nSignalsWasLeft = 0; // do not open the gate
* // below again.
* }
* else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
* nWaitersGone = 0;
* }
* }
* }
* else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or
* // spurious semaphore :-)
* sem_wait( semBlockLock );
* nWaitersBlocked -= nWaitersGone; // something is going on here
* // - test of timeouts? :-)
* sem_post( semBlockLock );
* nWaitersGone = 0;
* }
* unlock( mtxUnblockLock );
*
* if ( 1 == nSignalsWasLeft ) {
* if ( 0 != nWaitersWasGone ) {
* // sem_adjust( semBlockQueue,-nWaitersWasGone );
* while ( nWaitersWasGone-- ) {
* sem_wait( semBlockQueue ); // better now than spurious later
* }
* } sem_post( semBlockLock ); // open the gate
* }
*
* lock( mtxExternal );
*
* return ( bTimedOut ) ? ETIMEOUT : 0;
* }
*
* signal(bAll) {
*
* [auto: register int result ]
* [auto: register int nSignalsToIssue]
*
* lock( mtxUnblockLock );
*
* if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
* if ( 0 == nWaitersBlocked ) { // NO-OP
* return unlock( mtxUnblockLock );
* }
* if (bAll) {
* nWaitersToUnblock += nSignalsToIssue=nWaitersBlocked;
* nWaitersBlocked = 0;
* }
* else {
* nSignalsToIssue = 1;
* nWaitersToUnblock++;
* nWaitersBlocked--;
* }
* }
* else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
* sem_wait( semBlockLock ); // close the gate
* if ( 0 != nWaitersGone ) {
* nWaitersBlocked -= nWaitersGone;
* nWaitersGone = 0;
* }
* if (bAll) {
* nSignalsToIssue = nWaitersToUnblock = nWaitersBlocked;
* nWaitersBlocked = 0;
* }
* else {
* nSignalsToIssue = nWaitersToUnblock = 1;
* nWaitersBlocked--;
* }
* }
* else { // NO-OP
* return unlock( mtxUnblockLock );
* }
*
* unlock( mtxUnblockLock );
* sem_post( semBlockQueue,nSignalsToIssue );
* return result;
* }
* -------------------------------------------------------------
> "Slava M. Usov" wrote:
[...snip...]
> You're trying to position condvars as something ultimate
>> in synchronization,
>
>
> Yes, I do.
>
>
>> which they are simply not,
True, condition variables with mutexes would be interesting to adopt as the
sole thread-synchronization primitives if and only if interthread
synchronization mechanisms are a fossil fuel which must be harshly conserved &
rationed, lest we run out. But there is no such need for radical conservation
nor oppressive pruning of interthread synchronization mechanisms. If you do not
like semaphores, then do not use them. (If you do not like the television
program, then change the channel.) Simply not using them is easier than going
on a worldwide cross-industry crusade against semaphores in Boost, various
newsgroups, various WWW-sites, and Lord knows where else. But for the sake of
those software engineers in the realtime embedded software industry who know how
to successfully use POSIX semaphores (and their RTOS semaphore analogues) and
POSIX realtime signals/events (and their RTOS realtime signals/events
analogues), leave those experts to do their work without censorship and without
oppression and without derision.
The purpose of POSIX is not to be some sort of haughty
ram-it-down-one's-throat overly-academic political campaign to constrain the
computer industry via narrow preapproved cattle chutes. The purpose of POSIX is
to portably represent operating systems, both general-purpose OSes as well as
realtime OSes. Censoring semaphores with the goal of causing semaphores to
become extinct obstructs portability between RTOSes and POSIX, where POSIX is
the most effective standard unifying RTOS APIs today. Obstruction of
portability runs contrary to POSIX's mission. Alexander, please give semaphores
a rest. Semaphores are not pure evil. Semaphores are not Hell running rampant
thoughout an otherwise perfect-paradise. Many engineers in realtime embedded
systems have used semaphores successfully for decades. Semaphores are an
integral lucid portion of two very successful and very widely deployed
time-honored idioms: (multi)producer-(multi)consumer and pool-dispenser. See
http://groups.google.com/groups?q=Daniel+Miller+group:comp.programming.threads&hl=en&lr=&selm=3CD1864A.10401%40tellabs.com&rnum=3
And the same goes for all of you staunch Boost.threads defenders
1) who condone the removal of semaphore from Boost.threads, the lack of a
(multi)producer-(multi)consumer message-queues (a la pSOS message-queues), and
the lack of realtime/queued signals/events (a la pSOS events) and
2) who ignore the applicability of Boost.threads to embedded real-time
software, including ignoring the need to support RTOS concepts & mechanisms in a
C++ standard library:
give it a rest and embrace decades-long-standing RTOS multithread models as a
supported school of thought regarding threaded software. Extrapolate & unify
the C APIs of pSOS and VxWorks and pthreads and POSIX's realtime extensions via
a C++ class treatment of the MT topic.
And the same goes for all of you staunch proprietary Microsoft Windows &
Windows CE & Win32 defenders
1) who condone the the lack of a (multi)producer-(multi)consumer
message-queues (a la pSOS message-queues) and the lack of
realtime/queued/nonlossy signals/events (a la pSOS events);
2) who condone the lack of support of the POSIX.1-series; and
3) who obstruct the ability for Windows & Windows CE to act as a drop-in
functional-replacement for embedded realtime operating-systems, including
ignoring the need to support RTOS concepts & mechanisms in the Windows & Windows
CE operating systems:
give proprietarianism a rest and embrace pthreads and POSIX's realtime
extensions (and thus join the RTOS community which has already embraced those C
APIs in recent years).
Alexander, in prior newsgroup postings you have described your vision for an
alternative to Boost.threads as pthreads++. I deduce from your utter abhorrence
of semaphore that a whole POSIX++ or a whole POSIX.C++ (a superset of a
pthreads++) would actually not satisfy your pthreads++ goal after all, because a
POSIX++/POSIX.C++ would naturally include a C++ifying of the POSIX semaphore
system calls mentioned below. [Here POSIX.C++ would be a C++ language binding
for POSIX a la POSIX.5 and POSIX.9 for Ada and Fortran, respectively.]
>>>"A far more attractive synchronizing tool,
>>> the semaphore, was invented by Dijkstra in
>>> 1965. [4, 5]..."
>>>
>>Which is a part of Win32.
>>
>
> And which is *NOT* a part of POSIX Threads,
> for *really good reasons*... you just FAIL
> to SEE, unfortunately. ;-(
Semaphores are part of POSIX.1's realtime extensions (as are other
multithreaded topics)
sem_close
sem_destroy
sem_getvalue
sem_init
sem_open
sem_post
sem_timedwait
sem_trywait
sem_unlink
sem_wait
Your wording leads the reader to believe that POSIX holds semaphores in
disdain or hatred or condemnation, which is not the case at all (or else
semaphores would be absent). Semaphores were simply added later along with
realtime signals (a la pSOS events) and scheduling policies. You are
misrepresenting the topic.
http://www.opengroup.org/onlinepubs/007904975/functions/contents.html
>>one reason being their strict
>>serializing of threads being released from wait.
[...snip...]
>>Semaphores, say, do not have this property.
>>
>
> Internally, they DO.
Semaphores have this property if implemented via condition-variables. That
is only one possible implementation---a poor inefficient
overly-abstracted/unnecessary implementation which is uncommon in RTOSes, many
of which have had neither condition variables nor Hoare monitors. I encourage
everyone to take a look at the internal implementation of semaphores in pSOS.
>>Events do not have that property either.
>>
>
> Internally, they DO.
Events/realtime-signals have this property if implemented via
condition-variables. That is only one possible implementation---a poor
inefficient overly-abstracted/unnecessary implementation which is uncommon in
RTOSes, many of which have had neither condition variables nor Hoare monitors.
I encourage everyone to take a look at the internal implementation of
realtime/nonlossy events in pSOS (analogous to realtime/queued signals in POSIX).
I just meant that "you have to do that" is stronger than "you do that".
>[Problem with win32: multiple waiters, and how to reset the event?]
>And generally you don't hear win32 programmers complaining of the former
>all that much.
Heh. That's the complaint (and the only complaint) I made about them, from
the start. It seemed to be an admission that all the win32-defenders have
made in this thread.
--
Lucian Wischik, Queens' College, Cambridge CB3 9ET. www.wischik.com/lu
[...RTOSes/realtime-semas-stuff...]
Daniel, could you please show us ANY solution
(in source {pseudo-}code, please) which would
demonstrate the "superiority" of semas? As for
my part, I've already mentioned a couple of
SPECIFIC reasons why to avoid them. Sorry, but
to me, you've just failed (so far ;-)) to
"address" ANY of them.
regards,
alexander.
P.S. <"selected" refs [a couple of "new ones, BTW] ;-)>
http://groups.google.com/groups?selm=c29b5e33.0201310709.3ffc3476%40posting.google.com
http://groups.google.com/groups?selm=slrn9e684t.hp.kaz%40cafe.net
http://groups.google.com/groups?selm=32F5D80A.446B%40zko.dec.com
http://groups.google.com/groups?selm=336DB34B.63DA%40zko.dec.com
http://groups.google.com/groups?selm=3573E4A3.99A61075%40zko.dec.com
http://groups.google.com/groups?selm=37400BDF.6E42E28%40zko.dec.com
> Daniel Miller wrote:
>
> [...RTOSes/realtime-semas-stuff...]
>
> Daniel, could you please show us ANY solution
> (in source {pseudo-}code, please) which would
> demonstrate the "superiority" of semas?
I will do so eventually, but not here in this informal forum and probably not
on the immediacy-based time-line that you probably seek.
> As for my part, I've already mentioned a couple of
> SPECIFIC reasons why to avoid them. Sorry, but
> to me, you've just failed (so far ;-)) to
> "address" ANY of them.
This isn't about one-upmanship competition between semaphores &
condition-variables. This isn't about a fight-to-the-death between semaphores &
condition-variables (because I am not in favor of the death of either one).
This is about teaching tolerance of both.
If in a completely different context I were to argue against racism inflicted
against human race x for example, I would not attempt to show the superiority of
x to another race y (neither macroscopically for all desirable metrics nor
microscopically for any single one desirable metric), nor would I need to do so,
nor should anyone compel me to do so. But, I would try to undermine any claims
that y is vastly superior to x in every desirable metric---a symptom of the
racism against x---by attempting to teach tolerance of x as an equal peer of y
where each has its strengths & weaknesses. But also, I would try to undermine
any claims that x should be thoroughly exterminated---a symptom of the racism
against x. I would argue that races x and y both should be allowed to co-exist
in a live-&-let-live philosophy. Let them go forth, live long, and prosper.
Again Alexander, I am very curious about your viewpoints regarding the
inclusion of support for POSIX's semaphores in a hypothetical POSIX.C++ since
you advocate a more limited concept which you refer to as pthreads++ which
presumably omits semaphores. Could you tolerate some future POSIX.C++ binding
for POSIX.1 which includes semaphores (since POSIX.C++ would be a strict
superset [including among other things: semaphores] of your pthreads++ vision)?
Or would the mere presence of semaphores in that hypothetical POSIX.C++ lead
to your opposition to that POSIX.C++ including semaphores? Please feel free to
use private email to me instead of newsgroups if you wish.
First off, this is about UNDERSTANDING *pros and cons*
w.r.t. different SYNCHRONIZATION CONCEPTS/TOOLS (modern
POSIX mutexes & condvars on one side and archaic POSIX
semas on another side... MS-win32-silliness/brain-damaged-
stuff aside) AND IN THE CONTEXT OF *THREADS* >>"medium to
fine-grained structuring mechanism for parallelism in an
application"<< (*NOT* SIGNALS, IPC, or whatever things
"like that").
> If in a completely different context I were to argue against racism inflicted
> against human race x for example, I would not attempt to show the superiority of
> x to another race y (neither macroscopically for all desirable metrics nor
> microscopically for any single one desirable metric), nor would I need to do so,
> nor should anyone compel me to do so. But, I would try to undermine any claims
> that y is vastly superior to x in every desirable metric---a symptom of the
> racism against x---by attempting to teach tolerance of x as an equal peer of y
> where each has its strengths & weaknesses. But also, I would try to undermine
> any claims that x should be thoroughly exterminated---a symptom of the racism
> against x. I would argue that races x and y both should be allowed to co-exist
> in a live-&-let-live philosophy. Let them go forth, live long, and prosper.
Hehe. ;-) Is this an attempt to trigger Godwin's Law? ;-) ;-)
> Again Alexander, I am very curious about your viewpoints regarding the
> inclusion of support for POSIX's semaphores in a hypothetical POSIX.C++ since
> you advocate a more limited concept which you refer to as pthreads++ which
> presumably omits semaphores.
Yep (hypothetical pthreads++ SHOULD DEFINITELY
OMIT SEMAPHORES, I believe strongly).
> Could you tolerate some future POSIX.C++ binding
> for POSIX.1 which includes semaphores (since POSIX.C++ would be a strict
> superset [including among other things: semaphores] of your pthreads++ vision)?
Yup (see below).
> Or would the mere presence of semaphores in that hypothetical POSIX.C++ lead
> to your opposition to that POSIX.C++ including semaphores?
Nope (and relevance/importance of my "humble
opposition/tolerance" aside; I don't really think
that anyone cares much in regards to my "opposition"
and/or "tolerance" whether it's humble or not ;-)).
Hypothetical POSIX.1++ (POSIX.C++) would have to provide
semas to perform signaling from async.signal handlers
and for IPC (in both cases there could/should be {almost}
NO thread-shared memory involved, which, otherwise, could
and SHOULD be used *for mutexes and condvars to build
whatever sync.protocols "over" thread-shared data*).
That's it. Since neither signals nor IPC should (IMNSHO)
be a part of "limited concept which I refer to as
pthreads++", they aren't really welcomed/needed
there (in pthreads++, I mean).
regards,
alexander.
[...]
> POSIX mutexes & condvars
[...]
> MS-win32-silliness/brain-damaged-stuff aside
If you're discussing POSIX and don't care about win32, why don't you just
stop cross-posting that in win32 newsgroups?
Followups set. The subject line might also need some changing, I guess.
Happy zealotry.
S
> "Alexander Terekhov" <tere...@web.de> wrote in message
> news:3CECD17B...@web.de...
>
> [...]
>
>
>>POSIX mutexes & condvars
>>
>
> [...]
>
>
>>MS-win32-silliness/brain-damaged-stuff aside
>>
>
> If you're discussing POSIX and don't care about win32, why don't you just
> stop cross-posting that in win32 newsgroups?
Win32 should comply with POSIX.1-series. I care deeply that Win32 embraces
POSIX.1-series APIs, especially in the pthreads & realtime categories.
Win32 is an operating system interface.
POSIX.1-series specifies operating system interfaces. Nearly every
32-bit/64-bit operating system (except Win32) complies with all or most of the
POSIX.1-series. Even many RTOSes (which have been stand-off-ish for decades
when it came to being similar to hosted/general-purpose operating systems)
support all or most of the POSIX.1-series APIs. Even Mac OS supports the much
the collective POSIX.1-series API.
There is a desire to port software to Win32. Win32 should support *the*
standard for portable operating system interfaces and cease obstructing portability.
Are you saying that the ignorance of prior art was deliberate?
Tom
> Win32 should comply with POSIX.1-series. I care deeply that Win32
> embraces POSIX.1-series APIs, especially in the pthreads & realtime
> categories.
You misunderstood my message. If you want to create POSIX-on-win32, fine,
keep on posting to win32 forums. But the particular message that I followed
up contained nothing of that kind, it again contained boring idealistic
stuff what POSIX should be, not even how it should be [which was partly true
for the preceding part of the thread]. That has no relation to win32.
I believe it is improper to say that win32 should comply to POSIX anything.
It is an API which is completely unrelated to that. You might have probably
meant NT in whole, which should indeed support some POSIX level, but this is
separate from win32. Even the castrated POSIX NT has is not a part of win32
and is not on top of win32. And pthreads, of course, are out of the question
with the "standard" NT POSIX, you need either a replacement of the POSIX
subsystem [there are some] or an emulation of that on top of win32. In any
case, win32 does not support and is unlikely to ever support POSIX.
> Win32 is an operating system interface.
Yes. Unrelated to POSIX. Not declared as POSIX-compliant.
> POSIX.1-series specifies operating system interfaces. Nearly every
> 32-bit/64-bit operating system (except Win32) complies with all or most of
> the POSIX.1-series. Even many RTOSes (which have been stand-off-ish for
> decades when it came to being similar to hosted/general-purpose operating
> systems) support all or most of the POSIX.1-series APIs. Even Mac OS
> supports the much the collective POSIX.1-series API.
Yes, it is true and it is equally true that Win32 is unlikely to become
POSIX-compliant, at least in coming years. Even if it becomes POSIX
compliant it will do that by incorporating POSIX functionality and leaving
"win32 proper" intact, which is going to be a big mess. It is a pity but
that is the way it is.
> There is a desire to port software to Win32. Win32 should support
> *the* standard for portable operating system interfaces and cease
> obstructing portability.
win32 does not. Sorry, but it does not. You may speak of running some
POSIX-compatibility level on top of win32, but then it makes sense to
discuss how you're going to implement that on win32, not just state
"MS-win32-silliness/brain-damaged-stuff aside". No matter how many times one
may state that rubbish, win32 "inadequacies" [from POSIX' or pthreads'
viewpoint] will not disappear, will not be replaced by anything in win32,
will not make building POSIX for win32 any easier.
S
Because of this (for example; that's just ONE
"reason"... among many others):
"-------- Original Message --------
Message-ID: <3CECE756...@web.de>
Date: Thu, 23 May 2002 14:57:58 +0200
From: Alexander Terekhov <tere...@web.de>
Reply-To: tere...@web.de
Newsgroups: gmane.comp.lib.boost.devel
Subject: Re: Semaphores?
References: <3CEC2AD3...@ix.netcom.com>
Dave Jones wrote:
>
> Are there any plans to add semaphores to the boost threads library? Or
> are they already there and I missed them?
< Forward Inline >
-------- Original Message --------
Message-ID: <3CECD17B...@web.de>
Date: Thu, 23 May 2002 13:24:43 +0200
From: Alexander Terekhov <tere...@web.de>
Reply-To: tere...@web.de
Newsgroups: comp.os.ms-windows.programmer.win32,comp.programming.threads,microsoft.public.win32.programmer.kernel
Subject: Re: The implementation of condition variables in pthreads-win32
References: <40726f20.02032...@posting.google.com> <3CDF67F7...@web.de> <uFrvvgo#BHA.1916@tkmsftngp04> <3CDFE0B4...@web.de> <e9d19pq#BHA.2344@tkmsftngp02> <3CE0C501...@web.de> <eEk4KY3#BHA.2336@tkmsftngp05> <3CE18E0C...@web.de> <u15b7m$#BHA.2520@tkmsftngp05> <3CE26636...@web.de> <ueMYocM$BHA.1980@tkmsftngp04> <3CE3A44F...@genuity.com> <eRV52fN$BHA.2552@tkmsftngp05> <3CE53FA0...@tellabs.com> <eaSF1Qd$BHA.2384@tkmsftngp02> <c29b5e33.02051...@posting.google.com> <u30rXT2$BHA.1208@tkmsftngp02> <3CEA23F2...@web.de> <uVLkL$LACHA.1836@tkmsftngp05> <3CEA50F8...@web.de> <3CEABA5A...@tellabs.com> <3CEAD4C0...@web.de> <3CEBBAB2...@tellabs.com>
Daniel Miller wrote:
[...]
> This isn't about one-upmanship competition between semaphores &
> condition-variables. This isn't about a fight-to-the-death between semaphores &
> condition-variables (because I am not in favor of the death of either one).
> This is about teaching tolerance of both.
First off, this is about UNDERSTANDING *pros and cons*
w.r.t. different SYNCHRONIZATION CONCEPTS/TOOLS (modern
POSIX mutexes & condvars on one side and archaic POSIX
semas on another side... MS-win32-silliness/brain-damaged-
stuff aside) AND IN THE CONTEXT OF *THREADS* >>"medium to
fine-grained structuring mechanism for parallelism in an
application"<< (*NOT* SIGNALS, IPC, or whatever things
"like that").
....."
> Followups set.
Your "Followup-To: c.p.t"-piss-off IGNORED. Learn how to
use message filters (killfiles or whatever you call them).
regards,
alexander.
P.S. http://groups.google.com/groups?selm=3CA39B04.62BD1A61%40web.de
(Subject: Re: Q: use CreateThread() and TerminateThread() and message procedure)
You've posted and cited a lot -- many thanks! To which of those
references are you referring here?
Tom Payne
: [...]
:> > until 1985
: [...]
:> http://groups.google.com/groups?selm=3BE7ABD3.6303D8E1%40web.de
: The article by Hoar is concerned with mutexes [called monitors there] and
: single-signal condvars which are simpler than multi-signal condvars. In fact
: they can trivially be implemented by using a Win32 mutex and a semaphore [as
: the article later on goes demonstrating]. Most of condvars complexity
: [implementation-wise in Win32] is related to delivering the signal to
: multiple waiters, especially if one wants to be efficient at that.
In Hoare's paper, he presented a somewhat kludgey version of broadcast
based on daisy-chained signalling -- see his handling of the okToRead
condition in his solution to the readers/writers problem. In 1980,
Lampson and Reddell presented a more efficient implementation of
broadcast -- see "Experience with proceses and monitors in Mesa" CACM,
February 1980, v23, no 2, pp 105-117. (IIRC, that paper also
discusses the use of timed waiting on conditions.)
[...]
: I can take back the word "pioneer" if you are unhappy about that. But in
: mainstream application programming threads had little appearance, if any,
: before Win32. Most of the RDBMS on UNIX and VMS normally had multiple
: processes and not multiple threads well into 90s. Same applies to other
: types of network servers. I hear it was different on mainframes, though.
Since you trace the origin of Win32 to the inception of OS/2, it
should be noted that in those days, mainframes were the mainstream.
The IBM programmers on the OS/2 effort came from mainframe and
real-time backgrounds, where they should have gotten lots of exposure
to the state-of-the-art in concurrent programming. By contrast, the
MS contingent was lead by VMS folks, who were used to giving each
process/thread/task its own address space, so some of this stuff might
have been new to them.
Tom Payne
> I believe it is improper to say that win32 should comply to POSIX
anything.
> It is an API which is completely unrelated to that. You might have
probably
> meant NT in whole, which should indeed support some POSIX level, but this
is
> separate from win32. Even the castrated POSIX NT has is not a part of
win32
> and is not on top of win32. And pthreads, of course, are out of the
question
> with the "standard" NT POSIX, you need either a replacement of the POSIX
> subsystem [there are some] or an emulation of that on top of win32. In any
> case, win32 does not support and is unlikely to ever support POSIX.
>
This discussion has been fascinating, although I wonder why it's in the
win32.programmer.kernel newsgroup sometimes.
Anyway, it's true that "Win32" is not the same as "NT", but the underlying
NT synchronization primitives are awfully close to the ones exposed by the
Win32 API.
By the way, I would never even think of creating commercial software based
on the NT POSIX subsystem.
Carl Appellof
Well, I'm not sure (context is somewhat lacking, I'd say). ;-)
Perhaps, these:
http://groups.google.com/groups?selm=slrn9e684t.hp.kaz%40cafe.net
http://groups.google.com/groups?selm=c29b5e33.0202011147.98b216e%40posting.google.com
http://groups.google.com/groups?selm=3C5A4701.FC906236%40web.de
http://groups.google.com/groups?selm=wnxF7.1274%24RL6.32514%40news.cpqcorp.net
http://groups.google.com/groups?selm=3BE7ABD3.6303D8E1%40web.de
http://groups.google.com/groups?selm=3BC83D15.46FA3731%40web.de
http://groups.google.com/groups?selm=3CEA50F8.28BD70CD%40web.de
http://groups.google.com/groups?selm=3B9DBCD0.B9832EAA%40web.de
And, in regards "better" condvars, specifically this:
(from that DEC-SRC paper)
"....
Even if threads take care to call Signal only when the predicate is
true, it may become false before a waiting thread resumes execution.
Some other thread may enter a critical section first and invalidate
the predicate. Therefore when a thread returns from a Wait it must
re-evaluate its predicate and be prepared to call Wait again. Return
from Wait is only a hint [Lampson 84] that must be confirmed. By
contrast, with Hoare's condition variables threads are guaranteed
that the predicate is true on return from Wait. Our looser
specification reduces the obligations of the signalling thread
and leads to a more efficient implementation on our multiprocessor.
...."
and this:
http://groups.google.com/groups?selm=3CEA50F8.28BD70CD%40web.de
"....
[1] http://groups.google.com/groups?selm=31C00450.2781%40zko.dec.com
http://groups.google.com/groups?selm=31B80BB0.59E2%40zko.dec.com
(Subject: Re: pthread_cond_wait is unfair (POSIX threads))
...."
:> The article by Hoar is concerned with mutexes [called monitors there] and
:> single-signal condvars which are simpler than multi-signal condvars.
: I think you have mis-read the article by Hoar. His monitor is not the
: same as a mutex.
Monitors are simply a stylized use of mutexes. Hoare uses a
Simula67-inspired object-oriented extension to Pascal. Monitors are
simply instances of a class having per-instance mutexes. His
mutex-begin locks the mutex and mutex-end unlocks.
: "The procedures of a monitor are common to all running programs, in the
: sense that any program may at any time attempt to call such a procedure.
: However, it is essential that only one program at a time actually
: succeed in entering a monitor procedure, and any subsequent call must be
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
i.e., locking the monitor's instance-specific mutex
Tom Payne
I cannot comment on "deliberate", since I was not among those who did that.
As for the prior art, events and semaphores were the prior art. Including
monitors and condvars could be decided against due to their relative novelty
and due to some performance issues they have in general case -- I've
commented on the latter in this thread and I'm not going to repeat that --
and since events and semaphores would have to be provided to take care of
those performance issues, they perhaps did not want to include yet another
kitchen sink. Again, I don't know what the reasons actually were. It is a
given these days.
S
[...]
> > If you're discussing POSIX and don't care about win32, why don't you
> > just stop cross-posting that in win32 newsgroups?
>
> Because of this (for example; that's just ONE
> "reason"... among many others):
[...]
> First off, this is about UNDERSTANDING *pros and cons*
> w.r.t. different SYNCHRONIZATION CONCEPTS/TOOLS (modern
> POSIX mutexes & condvars on one side and archaic POSIX
> semas on another side... MS-win32-silliness/brain-damaged-
> stuff aside) AND IN THE CONTEXT OF *THREADS* >>"medium to
> fine-grained structuring mechanism for parallelism in an
> application"<< (*NOT* SIGNALS, IPC, or whatever things
> "like that").
>
> ....."
So? It says POSIX twice and specifically excludes win32. So how is that
related to win32? If you mean POSIX-on-win32, let's talk about that, not
POSIX in general. For POSIX in general, and threading in general, there are
forums which are far more appropriate. Do you agree?
> Your "Followup-To: c.p.t"-piss-off IGNORED. Learn how to
> use message filters (killfiles or whatever you call them).
In this forum [ms.*.win32.*] I'd like to ignore messages that have nothing
to do with win32. Unfortunately, my news agent is not smart enough to detect
messages devoid of some particular content. Frankly, I don't know how to use
it, because so far I haven't had a need to learn that. I normally assume
that people who bother to post in technical forums and who are not spammers
are smart enough to detect when _they_ are off topic and _not_ to post; and,
believe it or not, it does normally work that way... you're among very
exceptions...
> P.S. http://groups.google.com/groups?selm=3CA39B04.62BD1A61%40web.de
> (Subject: Re: Q: use CreateThread() and TerminateThread() and message
> procedure)
Now you're identifying yourself with whom? With yourself of that message or
the people whom you told that? In the former case, you're wrong, since I
never wanted that you stop posting here, I only asked you to post about
win32 when you post in win32 forums. I mean, I could post here how my cell
phone operator sucks [badly, by the way], but I have a feeling it would be
off topic here. And if it's the latter case, well, I guess I needn't
comment?
S
Yes! Great! So those people were supposed to be real experts. In that case,
why did _they_ ever want to have events and semaphores and _not_ monitors et
al? It's been quite some time since I last read OS/2 1.x manuals/references,
but I'm reasonably sure they _had_ events and semaphores. Actually, about
semaphores I'm completely sure, because there was some sample code for that
version of OS/2 and they had a few long-long-long variable names, ending or
starting with the word "semaphore", and they _were_ semaphores.
> By contrast, the
> MS contingent was lead by VMS folks, who were used to giving each
> process/thread/task its own address space, so some of this stuff might
> have been new to them.
It was later; the concept of Win32 might well have been decided on before
that. Actually, it _had_ been decided on before, because I remember the
story about NT "mutant" objects, which were used to implement win32 and OS/2
mutexes. First they implemented "mutex" objects, then they discovered that
OS/2 requirements were somewhat different, so they rewrote the code and
renamed the object. That means win32 and OS/2 rules had been laid out
_before_ that. By IBM parallelism experts, among others.
What about "well into 90s" bit? Anybody want to say that *nix and VMS had
not been mainstream until "well into 90s"?
S
> This discussion has been fascinating, although I wonder why it's in the
> win32.programmer.kernel newsgroup sometimes.
Exactly. Sometimes it cleary does not belong here.
> Anyway, it's true that "Win32" is not the same as "NT", but the underlying
> NT synchronization primitives are awfully close to the ones exposed by the
> Win32 API.
Yes and no. All native API calls are 'alertable' so you can implement that
dreaded thread cancellation and Unix-style signals pretty comfortably. As
for the problem with suspend/resume, you can just _not_ use them in your
POSIX implementation, then you can use PulseEvent() and
SignalObjectAndWait() without fear.
> By the way, I would never even think of creating commercial software based
> on the NT POSIX subsystem.
Yes, but that's a different story.
S