What is on topic here

B

blmblm

What makes you think Seebs doesn't understand semaphores?
[...]

What make you think arguing with spinoza1111 will ever generate
anything but more noise?

There is that. I suppose if Seebs doesn't feel compelled to defend
himself then bystanders shouldn't take it upon themselves to do so.
But I was tempted, and I yielded to temptation, and if I owe the group
an apology for the off-topic post, I offer one.
 
S

Seebs

What makes you think Seebs doesn't understand semaphores?

Haven't you ever heard of an unsupported assumption?
I would be interested in hearing, from Seebs, what sort of differences
he had in mind when he wrote the sentences quoted above.

I'm not under the impression that they share a thread API. And while
obviously an experienced programmer can often build and maintain a
multithreaded program, I have never met anyone who thinks it is something
to undertake without a great deal of care. Well, wait. That's not true.
I knew someone on a video game forum who had the following beliefs:
1. As soon as people are used to threaded programming, it will
be no harder than any other kind of programming.
2. You can reliably identify gay men because they dress in a
"girly" fashion.
3. As of 2009, it was completely clear that Nintendo had lost
any hope of competing in the console market, and Sony had achieved
total dominance in the console market this generation.

The amazing thing is how precisely the truth values of these beliefs are
aligned.
I'll also comment in passing that the multithreaded programming
environments I'm most familiar with (OpenMP, POSIX threads, Java)
either don't provide explicit semaphores at all or provide them
in addition to other synchronization mechanisms that are apt to
be more useful to application developers.

Hmm. POSIX threads seem to have mutexes, not general semaphores. I haven't
used them heavily, though; I may have missed something. Come to think of it,
I think there's POSIX semaphores which aren't specific to pthreads.

-s
 
E

Ersek, Laszlo

The big win for me has been compound literals, actually. I love them.
Very handy, very idiomatic.

C99 6.5.2.5 "Compound literals", paragraph 10:

----v----
EXAMPLE 2 [...] in
void f(void)
{
int *p;
/*...*/
p = (int [2]){*p};
/*...*/
}

p is assigned the address of the first element of an array of two ints,
the first having the value previously pointed to by p and the second,
zero. [...]
----^----

Is the assignment correct because the end of an initializer is a
sequence point? (C99 6.5.2.5p7 and Annex C.) "p" is written to once and
read once, and the new value of "p" is not based on the previous value
of "p".

But the old value of p is read _to determine_ the new value of
p. The fragment above is analogous to 'p = p->next', both
of which are legal.

(Since I only code in C90, I have no working experience with compound
literals, so I apologize for any possibly upcoming stupidity on my
part.)

If I understand correctly, the expression statement above does the
following:
- defines an unnamed array object with automatic storage duration,
- initializes it to { *p, 0 },
- assigns its address to p.

I don't see how the contents of an array can necessarily influence its
address (= placement in memory). Consider the following expression
statements in place of the assignment above:

p = (int [2]){9};
p = (int [2]){i};

If an implementation is permitted by the standard to place the int[2]
array object on the stack at the same address independently from the
array's contents, then the new value of p doesn't depend on *p, and
hence the previous value of p either.

Thank you,
lacos
 
A

Antoninus Twink

What make you think arguing with spinoza1111 will ever generate
anything but more noise?

Just out of interest Keith, do you consider this post of yours quoted
above to be noise?
 
P

Peter Nilsson

Keith Thompson said:
[...]

What make you think arguing with spinoza1111 will ever
generate anything but more noise?


Do you consider Richard Heathfield's arguing with spinoza1111
to be any less noisy?
 
K

Kaz Kylheku

If you want to raise the S/N ratio in clc, you can do it far more
effectively by boosting the signal than by adding to the noise.

Surely you mean by /reducing/ the noise?

I don't know about that.

The S/N ratio grows rapidly toward infinity as N approaches zero; the downside
of N is definitely more fruitful in maximizing S/N than the upside of S.
 
K

Keith Thompson

Peter Nilsson said:
Keith Thompson said:
[...]

What make you think arguing with spinoza1111 will ever
generate anything but more noise?


Do you consider Richard Heathfield's arguing with spinoza1111
to be any less noisy?


No.
 
S

Seebs

Surely you mean by /reducing/ the noise?

No, I think he means adding to the noise.
The S/N ratio grows rapidly toward infinity as N approaches zero; the downside
of N is definitely more fruitful in maximizing S/N than the upside of S.

Right. But since you can't, in general, reduce noise by posting, your
practical options when posting are to add to signal or add to noise.
I think his point is that arguing over whether or not responding to Nilges
is noise is probably going to contribute more to noise than to signal,
while talking about C-related things for a while could well contribute
to signal.

-s
 
N

Nick Keighley

There is that.  I suppose if Seebs doesn't feel compelled to defend
himself then bystanders shouldn't take it upon themselves to do so.
But I was tempted, and I yielded to temptation, and if I owe the group
an apology for the off-topic post, I offer one.

oh, I wouldn't apologise. Plenty of other people get sucked into
Nilges's black hole. I respond to him if he's writing about technical
matters or raises an interesting technical point and don't get drawn
on personalities and insult slinging.
 
R

Richard Bos

Peter Nilsson said:
Keith Thompson said:
[...]

What make you think arguing with spinoza1111 will ever
generate anything but more noise?


Do you consider Richard Heathfield's arguing with spinoza1111
to be any less noisy?


No. Emphatically no. And several others as well. Nick!

Richard
 
T

Tim Rentsch

The big win for me has been compound literals, actually. I love them.
Very handy, very idiomatic.

C99 6.5.2.5 "Compound literals", paragraph 10:

----v----
EXAMPLE 2 [...] in
void f(void)
{
int *p;
/*...*/
p = (int [2]){*p};
/*...*/
}

p is assigned the address of the first element of an array of two ints,
the first having the value previously pointed to by p and the second,
zero. [...]
----^----

Is the assignment correct because the end of an initializer is a
sequence point? (C99 6.5.2.5p7 and Annex C.) "p" is written to once and
read once, and the new value of "p" is not based on the previous value
of "p".

But the old value of p is read _to determine_ the new value of
p. The fragment above is analogous to 'p = p->next', both
of which are legal.

(Since I only code in C90, I have no working experience with compound
literals, so I apologize for any possibly upcoming stupidity on my
part.)

If I understand correctly, the expression statement above does the
following:
- defines an unnamed array object with automatic storage duration,
- initializes it to { *p, 0 },
- assigns its address to p.

I don't see how the contents of an array can necessarily influence its
address (= placement in memory).

Perhaps it can't, but whether it can or not is irrelevant.
In the abstract machine, it is evaluating the compound
literal that produces the address that is stored into p.
Using the old value of p to initialize the first element
of the array is part of evaluating that compound literal.
Hence, the old value of p is read to determine the new
value. The fact that different old values of p all produce
the same new value doesn't matter, any more than it would
for an assignment like

i = 0 * i;

This expression always stores 0 into i, no matter what
(legal) value i had previously. Despite that the old
value of i must (in the abstract machine) be read to
determine the new value of i. Right?

Consider the following expression
statements in place of the assignment above:

p = (int [2]){9};
p = (int [2]){i};

If an implementation is permitted by the standard to place the int[2]
array object on the stack at the same address independently from the
array's contents, then the new value of p doesn't depend on *p, and
hence the previous value of p either.

What an implementation might do (or even, is permitted to do) to
evaluate an expression doesn't change the abstract semantics.
Implementations (_all_ implementations) must be faithful to the
abstract semantics, not the other way around. In the abstract
semantics the old value of p must be read as part of determining
the address of the compound literal, even if in an implementation
that address is always the same, indeed even if the address is
known at compile time.

Implementations must follow the abstract semantics. It's almost
always a mistake to go the other direction, ie, to try to reason
about what the abstract semantics are based on what an implementation
might decide to do.
 
B

blmblm

Haven't you ever heard of an unsupported assumption?

Rhetorical question?
I'm not under the impression that they share a thread API.

Maybe not, but I'd have said that the basic ideas are the same,
and that someone who understands those ideas shouldn't have too
much trouble adapting to a different API -- it's like once you
understand the basic ideas of a particular programming paradigm
(procedural, functional, etc.) learning a new language in the same
paradigm is just (!) a matter of figuring out its syntax and perhaps
a few idioms or quirks.
And while
obviously an experienced programmer can often build and maintain a
multithreaded program, I have never met anyone who thinks it is something
to undertake without a great deal of care. Well, wait. That's not true.
I knew someone on a video game forum who had the following beliefs:
1. As soon as people are used to threaded programming, it will
be no harder than any other kind of programming.
2. You can reliably identify gay men because they dress in a
"girly" fashion.
3. As of 2009, it was completely clear that Nintendo had lost
any hope of competing in the console market, and Sony had achieved
total dominance in the console market this generation.

The amazing thing is how precisely the truth values of these beliefs are
aligned.

Uh-oh .... I'm fairly sure #2 is false, but I'm inclined to think
that #1 might be true, especially for people who don't have years of
experience with sequential programming warping their brains :).

(I have no information on #3.)
Hmm. POSIX threads seem to have mutexes, not general semaphores. I haven't
used them heavily, though; I may have missed something. Come to think of it,
I think there's POSIX semaphores which aren't specific to pthreads.

On Linux systems at least there is an implementation of semaphores
that can be used with the platform's implementation of POSIX threads.
I believe this is an implementation of an optional part of the POSIX
standard(s?). There is also another implementation of semaphores
that works across processes, which I believe implements a more
central part of the POSIX standard(s?). I've written toy programs
with both implementations, but that's about as far as my knowledge
of them goes.
 
S

Seebs

Maybe not, but I'd have said that the basic ideas are the same,
and that someone who understands those ideas shouldn't have too
much trouble adapting to a different API -- it's like once you
understand the basic ideas of a particular programming paradigm
(procedural, functional, etc.) learning a new language in the same
paradigm is just (!) a matter of figuring out its syntax and perhaps
a few idioms or quirks.

I'm not totally sure about this. I would guess that there exist APIs
which have been called "thread APIs" which are substantially dissimilar.
Uh-oh .... I'm fairly sure #2 is false, but I'm inclined to think
that #1 might be true, especially for people who don't have years of
experience with sequential programming warping their brains :).

I don't think so. There's an entire category of problems which can exist
in threaded programs but can't in unthreaded programs. That means, I am
pretty sure, that it is permanently more-complicated.

I can see people shifting comfortably from, say, functional to procedural,
or from procedural to OO, and once they've made the switch, it's no big
deal. On the other hand, there are some things which genuinely impose
new complexity. As another example, I'd guess that hard real-time will
always be harder than non-real-time code.
On Linux systems at least there is an implementation of semaphores
that can be used with the platform's implementation of POSIX threads.
I believe this is an implementation of an optional part of the POSIX
standard(s?). There is also another implementation of semaphores
that works across processes, which I believe implements a more
central part of the POSIX standard(s?). I've written toy programs
with both implementations, but that's about as far as my knowledge
of them goes.

Yeah. The canonical thing you get if you scan the docs for "semaphores"
is an interprocess thing, not an interthread thing.

-s
 
S

spinoza1111

[ snip quoted signature ]
We have to read this post in conjunction with your stunning level of
ignorance about computer science and lack of real qualifications, Mr.
Seebach:
1.  The "heap" is NOT an MS-DOS artifact

Did he ever actually say it was?  Well, perhaps I don't understand
what you mean by "artifact" here.  What Seebs actually said, in his
Web page critiquing Schildt's book(s), was that "heap" was "a DOS
term", and he clarified in message ID

<[email protected]>

as follows:

None of that strikes me as a display of "stunning ignorance".  ?

It is in fact a display of stunning ignorance, because the C language
standard, as opposed to a textbook, is silent on how to implement C.
This is in part what a standard should be (although a mathematical
intuitionist would say that it's a good idea to define things
"constructively", and the rough equivalent in programming is defining
a language by means of a reference interpreter).

It is also a conscious decision of the standards team. I believe it
was a pretense of scientific asceticism (deliberately eliminating
discourse in a half-understood application of Ockham's razor) where
the real agenda was corporate (preserving the profits of vendors).

TW Adorno (a sociologist) noticed how this asceticism actually works
and is used in organizations. The Socratic pose (of knowing nothing)
is easy if you're in fact ignorant (let's say a psych major who
decided to enter programming not having taken ANY computer science
classes, and unwilling to rectify that aporia):

"The more intelligent of them have an inkling of what ails their
mental faculties, because the symptoms are not universal, but appear
in the organs, whose service they sell. Many still wait in fear and
shame, at being caught with their defect. All however find it raised
publicly to a moral service and see themselves being recognized for a
scientific asceticism, which is nothing of the sort, but the secret
contour of their weakness. Their resentment is socially rationalized
under the formula: thinking is unscientific."

The C standards people were in fact unable to create a new form of C
with sensible semantics. But in their "fear and shame" they were
reassured that they could pose as "scientific ascetics" who wouldn't
have to define how C actually works. They wouldn't have to forbid left
to right, random, or right to left evaluation of procedure parameters.
Thinking is after all "unscientific", especially in corporations,
since it might be disruptive.

Unfortunately, this doesn't help working programmers at all to
understand how C works, and Schildt was rectifying this by giving a
concrete example of how C would work. Because Seebach had NO computer
science education, and little math, he did not realize that in CS as
in a math class, concrete examples have to be used.

Furthermore, the "heap" is just not a DOS term. Seebs' statement was
factually inaccurate and highly misleading and much worse than
anything in Schildt.

Are you using the term "atomic semaphores" to mean something different
from semaphores as proposed by Dijkstra and discussed in textbooks on
operating systems?  Just curious.

I'm also curious about why an operating system has to implement
semaphores, as opposed to some other synchronization mechanism --
or perhaps you're using "semaphores" here in a rather generic
sense that would include equivalent mechanisms such as monitors
(as proposed by Hoare and Brinch Hansen)?

This is not an area of my expertise. However, I would not say that
Windows and Linux are wildly divergent at the computer scientific
level. Just as we've seen that SOME form of stack is implied by
function call, some form of semaphore lock is needed when multiple
processes are accessing memory.

The idea that "there might be wildly divergent forms of science" is
basically the sort of break room fantasies that half- and un- educated
programmers are fond of.
 
E

Ersek, Laszlo

C99 6.5.2.5 "Compound literals", paragraph 10:

----v----
EXAMPLE 2 [...] in
void f(void)
{
int *p;
/*...*/
p = (int [2]){*p};
/*...*/
}

p is assigned the address of the first element of an array of two ints,
the first having the value previously pointed to by p and the second,
zero. [...]
----^----
In the abstract machine, it is evaluating the compound
literal that produces the address that is stored into p.
Using the old value of p to initialize the first element
of the array is part of evaluating that compound literal.
Hence, the old value of p is read to determine the new
value.

Thank you.
lacos
 
B

blmblm

I'm not totally sure about this. I would guess that there exist APIs
which have been called "thread APIs" which are substantially dissimilar.

Could be. But I'm inclined to think that the libraries provided on
most mainstream platforms for creating and working with threads are
likely to provide roughly equivalent functionality.
I don't think so. There's an entire category of problems which can exist
in threaded programs but can't in unthreaded programs. That means, I am
pretty sure, that it is permanently more-complicated.

Could be. Then again, in circumstances in which there's something
inherently concurrent about the problem being solved, I'm inclined
to think that programs that express that concurrency may be easier
to write and reason about than programs that try to sequentialize
the problem.

(It's not that I don't think you have a point here. I just question
whether multithreaded programming will always seem as exotic and
difficult as it apparently does now.)
I can see people shifting comfortably from, say, functional to procedural,
or from procedural to OO, and once they've made the switch, it's no big
deal. On the other hand, there are some things which genuinely impose
new complexity. As another example, I'd guess that hard real-time will
always be harder than non-real-time code.


Yeah. The canonical thing you get if you scan the docs for "semaphores"
is an interprocess thing, not an interthread thing.

Yes. On the Linux system I'm using now, there are two implementations
of semaphores. One of them -- the one you're calling canonical -- is
indeed an interprocess thing. But there's also a second implementation,
defined in semaphore.h, that works across threads. It seems to be part
of a "realtime" extension to the base POSIX standard.
 
B

blmblm

[ snip ]
It is in fact a display of stunning ignorance, because the C language
standard, as opposed to a textbook, is silent on how to implement C.

Isn't that pretty much what he said?:
This is in part what a standard should be (although a mathematical
intuitionist would say that it's a good idea to define things
"constructively", and the rough equivalent in programming is defining
a language by means of a reference interpreter).

Isn't "reference implementation" the more-usual term here?
It is also a conscious decision of the standards team. I believe it
was a pretense of scientific asceticism (deliberately eliminating
discourse in a half-understood application of Ockham's razor) where
the real agenda was corporate (preserving the profits of vendors).

[ snip ]
This is not an area of my expertise. However, I would not say that
Windows and Linux are wildly divergent at the computer scientific
level. Just as we've seen that SOME form of stack is implied by
function call, some form of semaphore lock is needed when multiple
processes are accessing memory.

"Semaphore lock" might not be the best way to express what I'm
guessing is your intended meaning; "synchronization mechanism" or
"synchronization primitives" might come closer. Just sayin'.

[ snip ]
 
S

Seebs

Could be. But I'm inclined to think that the libraries provided on
most mainstream platforms for creating and working with threads are
likely to provide roughly equivalent functionality.

I'd guess they would. However, equivalent functionality may not mean a very
similar programming style. There are a couple of ways of doing inter-process
communication I know, which have "equivalent functionality", but which are
used so completely differently as to cause serious hassle.
Could be. Then again, in circumstances in which there's something
inherently concurrent about the problem being solved, I'm inclined
to think that programs that express that concurrency may be easier
to write and reason about than programs that try to sequentialize
the problem.

That's an interesting point! As an obvious example, a traditional "UI
thread" model for a user interface is WORLDS better than trying to piggyback
UI interactions with actual processing code.
(It's not that I don't think you have a point here. I just question
whether multithreaded programming will always seem as exotic and
difficult as it apparently does now.)

I don't think it'll always be all that exotic and difficult, but I'm pretty
sure that it will continue to be a harder problem.

When I was just starting out, linked lists were weird and exotic. (I can
still vaguely remember what that was like!) They were definitely much, much,
more exotic and difficult than plain old arrays.

Now, I use lists without a second thought, and I don't even worry about
sanity-checking the code unless something actually goes wrong, because I can
generally assume that I'm about as likely to screw up a linked list
implementation as I am to forget how to spell my name. They're certainly
no longer "exotic" to me.

But!

They're still somewhat more complicated to use than arrays.
Yes. On the Linux system I'm using now, there are two implementations
of semaphores. One of them -- the one you're calling canonical -- is
indeed an interprocess thing. But there's also a second implementation,
defined in semaphore.h, that works across threads. It seems to be part
of a "realtime" extension to the base POSIX standard.

Seems plausible. The term is nicely generic. I am sure that someone,
somewhere, has a "semaphore.h" described as "flags for communication"
which actually has a chart of the positions of the arms of a person
waving brightly colored flags to communicate at a distance.

-s
 
B

blmblm

I'd guess they would. However, equivalent functionality may not mean a very
similar programming style. There are a couple of ways of doing inter-process
communication I know, which have "equivalent functionality", but which are
used so completely differently as to cause serious hassle.

Could be. What I was thinking is that Windows probably provides
a set of library routines that's similar enough to the POSIX
threads routines that mapping from one to the other would not be
especially difficult, and that the same would probably be true
for most other mainstream platforms. That a particular platform
might also provide other ways of working with threads that are
not so similar -- I wasn't thinking about that, but of course
it's possible.
That's an interesting point! As an obvious example, a traditional "UI
thread" model for a user interface is WORLDS better than trying to piggyback
UI interactions with actual processing code.

Yes, that was one of the examples I had in mind! (And I'm glad
my meaning was relatively clear, because on re-reading I'm not
sure I expressed it very well.)
I don't think it'll always be all that exotic and difficult, but I'm pretty
sure that it will continue to be a harder problem.

When I was just starting out, linked lists were weird and exotic. (I can
still vaguely remember what that was like!) They were definitely much, much,
more exotic and difficult than plain old arrays.

Now, I use lists without a second thought, and I don't even worry about
sanity-checking the code unless something actually goes wrong, because I can
generally assume that I'm about as likely to screw up a linked list
implementation as I am to forget how to spell my name. They're certainly
no longer "exotic" to me.

But!

They're still somewhat more complicated to use than arrays.

Yeah, okay, maybe I'm being too optimistic to think that multithreading
will ever be no more difficult .... or even "not much more difficult".
Seems plausible. The term is nicely generic.

Indeed. In my thinking "semaphore" is an abstract data type,
which can be implemented in a number of different ways. At first
it seems a bit confusing that apparently on some platforms
there are multiple implementations, but perhaps having separate
implementations for interprocess and interthread synchronization
makes sense.
I am sure that someone,
somewhere, has a "semaphore.h" described as "flags for communication"
which actually has a chart of the positions of the arms of a person
waving brightly colored flags to communicate at a distance.

But I think this would *not* be an implementation of the semaphore ADT
as defined in computer science. :)?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top