subroutine stack and C machine model

S

spinoza1111

In <[email protected]>,

spinoza1111wrote:




As you love to say, Do Your Own Homework. You never bother to support
your claims. Why should I bother to support mine?

But of course there is a major difference, which is that I /can/
support my claims. So, constructed entirely from memory, here's a
freebie list of the first ten of your mistakes that I can call to
mind:

1) your assumption that anyone who disagrees with you is a Fascist, a
homophobe, a racist, a sexist, an anti-Semite, a secret agent, or
some combination thereof;

Interpretation and off-topic wrt programming
2) your claim that my longstanding appraisal of Schildt was (a)
innovative and (b) commercially motivated;

begs the question rather doesn't it
3) your claim that Schildt's writings on C are not riddled with
errors;

repeating yourself to pad your case is as dishonest as padding your
resume. Do you pad your resume? It's also as dishonest as referring to
hundreds of errors without a list as does your friend Seebach.

4) your confusion of evaluation order and commutativity;

That's your confusion. It's caused by overspecialization in C.
5) your claim that malloc cannot be used safely;

C can't be used with safety, therefore malloc() cannot be used with
safety.
6) your belief that loop control subexpressions are evaluated once
only;

I never had this belief and you know it. I coded the loop control in
the loop for clarity in some throwaway code, once, in 2003, and
because your vanity had been wounded by the popularity of my thread on
programming professionalism in 1999, you blew up this "error" to an
absurd point, embarassing the people like Programmer Dude foolish
enough to believe you.
7) your misunderstanding about the way the word "object" is used in C;

It's misused. A misuse cannot be "understood" for the same reason that
conceding Schildt is clear implies he's for the most part correct.
8) your claim that C requires functions to be defined prior to use (it
was never clear to me whether you were mixing up "declared" and
"defined" or were simply ignorant of C's prototype construct);

May have made it. I told you that I don't use C, having abandoned it
because of its lack of safety, but would relearn even from you if I
had to in order to end this meankids attack on Schildt.
9) your claim that "C cannot ethically be used for new development";

Question begging and a matter of opinion.
10) your invasions of implementation namespace;

You're babbling.
11) your pointless casting;

Extra material for clarity is a good programming practice. It enhances
readability,
12) your ignorance of free()'s ability to handle null pointers;

It's not a useful feature, is it? And in saying that it wasn't a
counterexample to Schildt, I nowhere implied I didn't know. Actually,
after reading Seebach, I knew. It's trivia unless you can show a use
for it other than covering up your own incompetence.

13) your belief that a score in a broken test is meaningful;

Question begging, since your failure indicated your incompetence. And
your incompetence is the issue whether you like it or not.
14) your apparent belief that you have any idea at all of what you're
talking about.

Padding. Yes, I'd throw any resume from you into the wastebasket.
 
S

spinoza1111

In

spinoza1111wrote:




No, it uses sequence points (I know you don't know what they are, but
bear with me here) to specify evaluation order precisely.

Sequence points control evaluation order, so you may stop quibbling.
A sequence point is a point in the code at which all prior evaluations
and side effects have taken place (or at least a strictly conforming
program can't tell that they haven't), and no subsequent evaluations
or side effects have yet taken place (parenthetical ditto).

Thus, in the code:

a=b; c=a;

the introduction of a sequence point after the first assignment
guarantees that the assignment of b's value to a is complete before
the next assignment begins (or at least that a strictly conforming
program won't be able to tell if it isn't).


And, like all your cheap shots, it was over-priced.


Several errors here. Firstly, they're called "sequence points", not
"sync points". Secondly, you claim knowledge of the identity of their
inventor but it's fairly obvious that you don't have that knowledge.
Thirdly, your reference to "unqualified people" is clearly a dig at
Peter Seebach, who served on the C99 committee, but the concept
certainly existed in C89. Fourthly, let's take a look at some people
who do not have Computer Science degrees, and therefore surely count
as unqualified: Alfred Aho, Tim Berners-Lee, Whitfield Diffie, Edsger
Dijkstra, Robert Floyd, Martin Hellman, C A R Hoare, John Kemeny,
Stephen Kleene, Donald Knuth, Andrey Kolmogorov, Thomas Kurtz, Doug
McIlroy, Marvin Minsky, John von Neumann, Alan Perlis, Claude
Shannon, Alan Turing, and of course Harry Huskey.

These people are different from Seebach because when they started
work, there was no computer science. They CREATED it. Whereas Seebach
started out, it appears to me, in the 1990s, and had for this reason
no excuse for not majoring in cs, or at least taking a class, before
serving on a standards board. Furthermore, most of these men and women
created new technology as opposed to destroying it, and they acted
collegially; one of Dijkstra's essays was "How Do We Tell Truths That
Might Hurt?" Dijkstra's writing characterised what he felt to be wrong
ideas and NOT ONCE did he make a person's name into a foul word.
 
S

spinoza1111

...
 >                                                        For example,
 > Peter Seebach hasn't taken any computer science classes whatsoever yet
 > has tried to destroy the reputation of someone who has.

I have taken none either, for the simple reason that when I was at university,
computer science was not yet taught as a subject (this was from 1962-1969,
computer science was introduced around 1975).  Stronger, the university were
I was had did only own computers for administrative purposes, for everything
else they used the computer of the institute where I started working in 1969,
and where I am still working.

FYI: Edsger Dijkstra didn't take any computer science class either.

Because there was no computer science, whereas based on his writings,
he would be horrified to find a person who could have majored or
minored in CS serving on a language standard. He strongly emphasised
the need to use existing work as is done in other scientific fields,
and he strongly protested the use of folklore.
 
B

Ben Bacarisse

Okay, given that, it seems to me that the only expressions which can
be, from analysis of syntax, "known not to contain any side effects",
would be constant expressions. Any expression involving a variable
could, if the variable is volatile-qualified, have side-effects. But
you can't tell by looking at syntax whether a variable is volatile-qualified,
because syntactically, that's just a "type qualifier", and you can't tell
it from const or restrict.

That is not how I would use the term. By analogy, int and char are
just "type specifiers" so would you say that you can't tell the type
of int i; by looking at syntax? You may be making a more subtle
distinction here that I've missed.
So there's no way you can tell:

const int i = 3;
from
volatile int i = 3;
at the syntax level, and the latter looks to me to contain a side
effect.

I would say that you *can* tell them apart "from the syntax" but that
is not a formal phrase with any formal meaning. Spinoza1111 wants to
go further and include everything that can be determined from static
analysis as being "syntax" but, personally, I would not go that far.

Of course, a very general grammar can express anything that can be
computed by machine, so there is *a* grammar that can classify C
statements as having side-effects -- to the extent that it is possible
to do so at all. A full classification is impossible since it would
require a solution to the halting problem, but I doubt that that is
what most people mean by a "syntactic property" of a C program.

<snip>
 
J

jacob navia

Barry a écrit :
Yep, I was wrong with enough overkill it can be done :)

There is no "overkill", just a carefully crafted design. A function
table is a normal construct in C, used in many important pieces
of software. It allows for very good interfaces. See for instance all
COM interfaces.
 
S

Seebs

I showed code in C that does exactly that. If the common
operations in all containers are at the same place in the virtual table
they are binary compatible and all of them can be used with the same
interface.

Hmm. You have a point; you can't do it generally in C, but if you're
looking only at a very specific subset, you can nail down the set of
common components and make that work. So you could have a
container/array/list set, where the list ops are a proper superset of the
container ops and have a common initial sequence...

-s
 
S

Seebs

That is not how I would use the term. By analogy, int and char are
just "type specifiers" so would you say that you can't tell the type
of int i; by looking at syntax? You may be making a more subtle
distinction here that I've missed.

Yes.

Syntax is not the same as semantics! The difference between 'float' and
'double' is introduced, not under the heading "Syntax", but under the heading
"Semantics".
I would say that you *can* tell them apart "from the syntax" but that
is not a formal phrase with any formal meaning.

It is, in C. See section 6.7.2 in C99; "Syntax" gives a list of things
which could be type specifiers, "Constraints" says that there must be at
least one and lists the allowed combinations, and "Semantics" explains how
the type specifiers specify types.
Of course, a very general grammar can express anything that can be
computed by machine, so there is *a* grammar that can classify C
statements as having side-effects -- to the extent that it is possible
to do so at all. A full classification is impossible since it would
require a solution to the halting problem, but I doubt that that is
what most people mean by a "syntactic property" of a C program.

It's really hard to tell. Keep in mind we're dealing with Spinny, who
is not "most people".

-s
 
T

Tim Streater

[snip]
C itself was produced by men without a CS degree. As a result, its
design was in part an adolescent and emotional response to Multics and
PL/I and as a result we have to put up with its many mistakes,
including a for loop which doesn't follow the Fortran model.

Ah, now this is interesting. I'd like to know in what you believe that
the C for-loop doesn't follow the Fortran model, and why you think this
is a mistake.
 
S

spinoza1111

Yes.

Syntax is not the same as semantics!  The difference between 'float' and
'double' is introduced, not under the heading "Syntax", but under the heading
"Semantics".


It is, in C.  See section 6.7.2 in C99; "Syntax" gives a list of things
which could be type specifiers, "Constraints" says that there must be at
least one and lists the allowed combinations, and "Semantics" explains how
the type specifiers specify types.

You keep unlearning what you have learned already. Not good.

You realized earlier that I did not claim one could in general detect
whether a construct has side effects. Yes, this (esp. in C) is an
instance of the halting problem. I claimed that there exists a set of
constructs which can be declared side effect free independent of the
halting problem. Even with sync points, if the preprocessor is not in
use, and "all other things being equal",

int a; a=1;

belongs to the "set of constructs for which there is no side effect
such that this nonexistence is verifiable".

The existence of this set (call it NSEV) is experimentally confirmed
by the possibility of optimizing C code whenever code motion assumes
no side effect in the moved code.

It's also confirmed by "hand motion" (when a C programmer moves code
when he thinks he has confirmed that the code has no side effects).

NSEV is computable: see Aho/Sethi/Ullman on optimization. You don't
move code (for the most part) unless it's in NSEV. Not NSE since this
is a (proper) superset of NSEV, and you cannot justify moving
statements in NSE-NSEV since NSE-NSEV is uncomputable. This is because
NSE can contain statements whose membership in NSE is unprovable,
either in theory as a result of the halting problem or pragmatically
owing to time and space limits.

NSEV membership is confirmed by syntactical analysis IN THE SENSE that
you don't run the code to see if it has no side effects. You instead
parse as much as you can bounded by a pragmatic limit. For example,
you determine NSEV after preprocessing and not before.

But Aho et al. do not call activities that include confirming
membership in NSEV syntactical nor do they treat it as front end. They
treat it as deep back end and they call it data flow analysis. They
also do not use my terms since of course they are concerned with more
than side effects.

Nonetheless, what they say about code transformation applies:

"...we are obliged to assure that all errors are in the 'safe'
direction"

In my terminology, misclassifying a construct as NSE is a safe
direction.

What's very disturbing to me is that looking over the C99 standard I
find that apparently to protect the profits of vendors, including the
vendors of buggy compilers that make errors in the unsafe direction,
the voting members, one of whom never took a computer science in his
life, never thought to use Aho et al. to define sequence points
precisely nor under what circumstances a+b could be transformed into b
+a.
It's really hard to tell.  Keep in mind we're dealing with Spinny, who
is not "most people".

My name is not Spinny, but I am proud to be unlike "most people" here.
 
S

spinoza1111

I don't think he ever said that one could.  Nash won in 1994:http://nobelprize.org/nobel_prizes/economics/laureates/1994/

That was a joke son. Most of us know Nash won the Nobel Memorial prize
in economics, with a little bit of help from many members of the staff
of Princeton University Information Centers, of which I was one.
Strangely, although the White House claims that the Administration
knew nothing of Obama's being in the running for the Peace prize this
year, it was known that Nash was in the running for the Economics
prize. I was informed of this when asked to help him with C.
 
S

spinoza1111

I normally don't think apologies work that way.  In general, I apologize
if I am convinced that I was in error (or that I harmed someone inadvertantly
in a way that I regret, etc.), and I don't waste time worrying about whether
other people do the same.

Basically, look at it this way:

Consider the likelihood, given a claim from that particular poster, that
you would believe the claim to be true on the grounds that he asserted it..
What does this tell you about a hypothetical case where he claims to be
sorry for something?  From what I've seen, he'd be wrong more often than
not...

Peter, we're waiting for you to apologize to Schildt and remove "C:
The Complete Nonsense".

I have TWICE made the error of confusing comma as operator with comma
as parameter separator, and twice I have apologized immediately.

Here, you do what you do to Schildt. You make no new argument
confirming one of my errors and you make no knew argument confirming a
new error. Instead, you referback to a set of errors which you never
defined.

Even that clown Heathfield has produced 14 "errors" and has been shot
down. Whereas you repeat something you never proved nor even claimed
in detail.

This is called amplification by repeated trashing, and I would like it
to stop. It's happened to me, it's happened to Navia, and it's
happened to Schildt and as a result this newsgroup is dominated by
you, despite the fact that you have never, by your own admission,
taken a computer science class (when an ACM approved curriculum has
been in existence since before you were born) and despite the fact
that Richard is also an autodidact without programming experience
outside of business programming.
 
B

Ben Bacarisse

Seebs said:
Yes.

Syntax is not the same as semantics! The difference between 'float' and
'double' is introduced, not under the heading "Syntax", but under the heading
"Semantics".


It is, in C. See section 6.7.2 in C99; "Syntax" gives a list of things
which could be type specifiers, "Constraints" says that there must be at
least one and lists the allowed combinations, and "Semantics" explains how
the type specifiers specify types.

That is too narrow for my taste but I accept it is a distinction that
can be made. You stated elsewhere that constant expressions are a
syntactic construct, but the definition requires the Constraints
section so presumably you include in "syntax" the constraints whilst
excluding all other restrictions?

Personally, I like to be able to say that one tell if an expression is
an integer constant expression by "looking at the syntax" of a program;
not least because such things are referred to in other Constraints
sections.

If you take syntax to be only syntax+constraints, then we have the
oddity that the syntax requires semantics. If you don't include
constraints, then the situation is consistent, but I then can't see
how constant expressions are syntactic.

My preference is simply not to treat these categories as having hard
boundaries because the specification does not seem formal enough to
support such a rigid distinction.

<snip>
 
S

spinoza1111

Richard Heathfield said:




spinoza1111wrote:
[...]
It happens to
be possible to tell the difference between "an expression known
not to have side effects" and "an expression which may have side
effects" from syntax alone even in C,
  int x = foo();
According to you, it is possible to determine whether the above
expression has side effects. I disagree. Please present evidence to
support your assertion. [...]

Richard, it appears that one of us has misinterpreted what
spinoza1111wrote.

And it appears that it's me. Mea culpa, at least on the basis of the
quoted text. (I'm not about to go digging for this one.)

Very good. And note that an error of misinterpretation of a person
who's been singled out is more grievous than normal. Therefore, you
need to apologize to me as well as admit the error. I shall look
forward to your apology for this mistake.
 
S

spinoza1111

Most people that I know who did Electronics, Math or Physics were and
are much better programmers than CS graduates. CS is a simple degree in
comparison and a lot of the output have an artificially high opinion of
themselves full of theory which they will never, ever use. Good
programming sense is generally common sense. Computer nerds are
frequently lacking in that.

This may very well be true as regards applications programming.
Electronics majors are probably better at writing code in support of
electronics, etc.

But not in the area of analyzing, compiling or teaching a programming
language. This is evident in the overly broad way in which the C99
standards forbids assumptions. As it happens, by 1999, two editions of
Aho/Sethi/Ullman had defined under what circumstances a+b could be
rearranged, but it appears that this work was unknown to at least one
voting member.
 
S

spinoza1111

In

spinoza1111wrote:


Wrong. The freedom for a conforming implementation to evaluate
expressions in an unspecified order does in fact come from the
Standard, which in turn comes from the committee that produced that
Standard.


Unlike the guy (Peter Seebach) who never took a computer science
class, you have failed to understand the issue here.


Whoosh, or what? The issue is order of evaluation, not commutativity.


You mean the Standard should prevent compilers from doing things
efficiently? Figures, I guess.

The Standard needed to define when code could be reordered and to
define the semantics of a baseline unoptimized C using a stack model.
It did not do so because at least one of its voting members had never
taken a CS class in his life and to avoid discommoding vendors who
could not produce compilers that would run in this way.

In no way would this prevent compilers from being "efficient". What
part of a "command line option" don't you understand?
  int x = foo();

According to you, it is possible to determine whether the above
expression has side effects. I disagree. Please present evidence to
support your assertion.

Your error of interpretation here, which exhibits a more global
incompetence and malicious intent than computing end limits in a for
loop, has now been corrected. Because of its malicious intent, you
need at this time to do more than admit wrong. You need also to admit
harm by apologizing.
Just as well he stayed away then, since the claim is false.

Seebach, unfortunately, did not stay away. Schildt did abstain,
perhaps because he saw what a vendor driven joke the standard was. Get
your facts straight.
 
S

spinoza1111

In <[email protected]>,

spinoza1111wrote:


And therefore they don't have CS degrees - just like Seebs.

They didn't have CS degrees because there was no CS. Instead they did
their best to apply their math degrees to create CS. As soon as they
began to compile a critical mass of papers they CITED each other when
they thought what they read worthwhile, and they NEVER made "negative
citation" ("don't read Bullschildt") a practice because to say "Nilges
is wrong", "Navia is wrong", and "Schildt is wrong" is almost null in
terms of useful knowledge. If I'm wrong, what is right? You haven't
told the listener, instead you have shit out your envy and your bile
on the floor.

Ben Bacarisse TODAY responded to a student who came to clc to get help
on a homework assignment which requires more knowledge than the
student's teacher had of recursive descent parsing. Instead of helping
the OP, Bacarisse told him not to listen to "Nilges".

Quite apart from the malice, put yourself in the shoes of the OP. He
is no wiser whereas I gave him a formal grammar and C Sharp pseudo
code, using pseudo code to avoid doing his assignment for him. In
fact, he's not only learned, not that "Nilges is wrong" (since he has
no reason for believing Bacarisse) but that there's a 50% probability
that ANYTHING he hears here is wrong.

This is like growing up with divorced parents who hate each other,
isn't it? Many kids in that situation turn to their peers and drugs
because there's a 50% chance that what the parent says is wrong.

It's fine to do applications programming when in place of a CS degree
you have majored in the application. But it's irresponsible to serve
as a standards committee member without having taken a CS class today.
Part of what CS students learn is the history of CS and its mistakes,
which include Algol 68 and its overly permissive evaluation rules.

C itself was produced by men without a CS degree. As a result, its
design was in part an adolescent and emotional response to Multics and
PL/I and as a result we have to put up with its many mistakes,
including a for loop which doesn't follow the Fortran model.

People also learn how to be collegial in college, don't they. In a
phone interview I conducted for my book, Peter Neumann, the respected
moderator of comp.risks, told me that Dijkstra and John McCarthy
didn't see eye to eye, yet NOT ONCE did either give each other's name
to errors. This was because while they did not "major in CS" they
learned from its predecessor fields how to act like adults instead of
children.

Furthermore, Dijkstra with great zeal taught several generations of
computer science majors at University of Texas. He hardly can be used
as a justification for some little snot-nose like Seebach boasting
that he's never taken a cs class!
Without (according to you) being qualified to do so. How naughty.

You really are both malicious and stupid, aren't you. Yes, they
CREATED it. And in the case of Algol 60 they did a good job by
specifying evaluation order. In Dijkstra's case especially they didn't
work for vendor interests, they worked in the public interest by
inventing constructs about which one could have positive knowledge,
not be exposed to the laughter of adolescents because of gotchas.

They being geniuses unlike Seebach were able to create in the same way
as Einstein. Don't you DARE compare yourselves to people like that
since you react like such apes to new ideas that haven't been blessed
by appearing on the Discovery channel or in some stupid computer
magazine.
 
S

Seebs

That is too narrow for my taste but I accept it is a distinction that
can be made. You stated elsewhere that constant expressions are a
syntactic construct, but the definition requires the Constraints
section so presumably you include in "syntax" the constraints whilst
excluding all other restrictions?

Not quite. Rather, I believe that, if you follow the syntax down far
enough, you can tell them apart, because constant values can be distinguished
from variables.
My preference is simply not to treat these categories as having hard
boundaries because the specification does not seem formal enough to
support such a rigid distinction.

Could be. In which case, the claim that you can tell whether or not something
could have side effects by looking at the syntax becomes essentially useless.

-s
 
S

Seebs

And therefore they don't have CS degrees - just like Seebs.

To the best of my knowledge, back when I was in school, my school
didn't offer CS degrees, they offered math degrees with CS "concentrations".

In any event, I think this goes straight to the question of why trying
to figure out "status" is stupid. Work experience is a qualification.
Furthermore, the original point Spinny was making was his claim that all
the people disagreeing with him were ivory tower intellectuals who had
gotten into advanced and specialized CS without the benefit of the basics.
Clearly, untrue.

-s
 
S

spinoza1111

In <[email protected]>,





spinoza1111wrote:


But not misinterpretation.

It's not a programming mistake, nor it is a mistake. You're a cheap
little Fascist.
I agree that these silly assumptions of yours are off-topic, so please
stop doing it.



Wrong, AGAIN. Please stop being wrong /quite/ so often. I have already
demonstrated to you several times that my criticisms of Schildt's
writings (a) are pre-dated by many other similar criticisms by
others, and (b) themselves pre-date any association between myself
and my publisher.

Still begs the question as a simple informal fallacy. Your thesis is
that Nilges is a bozo who doesn't know what he's talking about. Your
proof is the statement that I don't, repeated ad nauseum. That's
petitio principii.

I've already said that I thought in the past that you started this
shit with Schildt, but that subsequently I tracked down your source to
one silly document, "C: The Complete Nonsense", by Seebach. All this
means is that you're not even smart enough to put together a silly
document, that you instead parroted this source foolishly, amplifying
the document so as to give the impression that it has substance. Which
on investigation we find it does not, being mostly silly assertions of
the sort my student Otto made in 1991, made from wounded vanity.
I'm not repeating myself. List items (2) and (3) are DIFFERENT, and
address different errors on your part.

Different words, same import.
My CV is already so long that I have had to edit it down severely. Why
pad it?

When you can't dazzle them with brilliance baffle them with bullshit.
When you can't baffle them with bullshit, copy and paste.
In practically every article you post, you make errors. An exhaustive
list of those errors would take far too long to construct.

Oh. I thought we were going to get a list. Turns out that we have a
Halting problem, Houston. Little Dickie-boy is all tired and prefers
again petitio-principii. To be proved: Nilges makes many mistakes.
Here is a list of all his mistakes. Oh, it's not a complete list. I
lied. The list is unbounded. Proof: Nilges makes many mistakes.

Fwizz. Nilges turns out to be a Universal Turing Machine or
mathematics itself, since he's either incomplete, or self-
contradictory, or cannot verify that he will ever halt (certainly is a
wordy chap that's for certain).

But unlike Turing or Godel, you have produced no proof.
No, it's your confusion and it's caused by ignorance.

There was a limey bastard from Blighty
Who acted all high and mighty
When asked for a proof, see,
He petitioned the principii
That stupid limey bastard from Blighty!

There is an asshole in England
Who ever the truth is manglin'
When asked for a list
He shot and he missed
What luck he was not at Agincourt a fightin'!

You merely repeat your error.

But once more, oh you fat bore, you haven't proven a thing
You assume that everything I say is wrong. To prove it,
You assume the Delphic posture and you say, what did he say?
It is wrong because he said it, and I most regret it.
Since you come in here all queer, to throw your weight around
Being considered I'd wot a sot down at the public house,
Being asked to leave by bartender Steve more than once,
You are scared of learning so you label it offtopic
And when it its topic spot on, you start running your foul mouth,
A mouth most foul, I say, that would be sweetened by a good round
oath,
That would be freshened by saying **** you,
Because out of your hole comes things meant to destroy.
You start shit in here, you fat ugly queer,
Without caring that you might cost people their jobs.
And when they respond like men you squeal like a pig
That they are no better than you, and therefore worse.
But "give me an ounce of civet, good apothecary"
In the Seventh Circle of Hell I too long tarry.

We have two choices - either you did have this belief or you didn't.
If you did, then your use of strlen in a loop condition can be
excused as mere woeful ignorance. If you didn't, however, then that
usage cannot be explained except by stupidity. Your call.

Oh **** you. Shut up.

"You have sat too long for any good you have been doing. Depart, I
say, and let us have done with you. In the name of God, go!” - Oliver
Cromwell
 

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

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,810
Latest member
Kassie0918

Latest Threads

Top