Massassi Forums Logo

This is the static archive of the Massassi Forums. The forums are closed indefinitely. Thanks for all the memories!

You can also download Super Old Archived Message Boards from when Massassi first started.

"View" counts are as of the day the forums were archived, and will no longer increase.

ForumsDiscussion Forum → Jon'C is awesome. Discuss.
12
Jon'C is awesome. Discuss.
2006-10-15, 5:11 PM #41
Quote:
Wrong. Prefix incrementation is modify-read. In a language sense, anyway. Assembly-wise yes, but what does it matter? The 'modify' part is atomic and that's what this implementation requires.


Thread A reads variable X into register F.
Thread B reads variable X into register G.
Thread A increments register F.
Thread A writes register F to variable X.
Thread B increments register G.
Thread B writes register G to variable X.

Times X was incremented: 2.
New value of X: X+1.

Your absolutely right, the 'modify part' of ++X was so atomic that the operations didn't stomp on each other at all.

Quote:
I'm sure that would be important if I were using C++ exceptions or anything that can throw a C++ exception in this code.

You default-constructed a rather large number of messages. If any of those constructors throws, you leak.

Quote:
Sure, I'll give you the fact that it would be about the same implementation time. But what actual features would it offer me? Apart from resizing, which I have said repeatedly is of absolutely no use or consequence to me?

Exception safety, automatic memory release, and insurance against you screwing up.

Quote:
Oh, and just in case you missed it, here is the rest of my post that you ignored completely. Possibly because you have no way to argue against it whatsoever.

I find it amazing that I both ignored it and quoted it at the same time!
Wikissassi sucks.
2006-10-15, 5:22 PM #42
JM: stop. You lost this argument a LONG time ago. Stop being a sore loser.
"it is time to get a credit card to complete my financial independance" — Tibby, Aug. 2009
2006-10-15, 5:24 PM #43
No, I won it the moment he claimed I didn't know C++, and I dropped a boost::spirit based recursive descent parser on him.
Wikissassi sucks.
2006-10-15, 5:29 PM #44
Originally posted by Isuwen:
Thread A reads variable X into register F.
Thread B reads variable X into register G.
Thread A increments register F.
Thread A writes register F to variable X.
Thread B increments register G.
Thread B writes register G to variable X.

Times X was incremented: 2.
New value of X: X+1.

Your absolutely right, the 'modify part' of ++X was so atomic that the operations didn't stomp on each other at all.
Except, as I stated, 'Thread B' cannot increment 'variable X' - only 'Thread A' can. On X86 a 32-bit store operation is guaranteed atomic, meaning that 'Thread A writes register F to variable X' will complete before 'Thread B loads variable X into register G'.

This is not the case on other systems: namely Alpha which only offers 16-bit granularity, and x86-64 (in 64-bit mode) which offers 32-bit granularity but a 64-bit size_t. My code is thread-safe but it's not terribly portable.

Quote:
You default-constructed a rather large number of messages. If any of those constructors throws, you leak.
Fortunately there is nothing in any of those constructors which can throw an exception. Which is, also, why I did not make my message queue class a template.

Quote:
Exception safety, automatic memory release, and insurance against you screwing up.
1.) Don't need it.
2.) Doing that myself already.
3.) Where is the insurance against the STL vendor screwing up? For instance: http://www.dinkumware.com/vc_fixes.html
This is old, but Dinkumware periodically releases bug fixes for their STL implementation which are not made available for VC users. The STL is not 100% safe, my code is not 100% safe, your code is not 100% safe. Fortunately, unlike your code, mine is very simple so if there is an issue I'm going to find it before you will.

Quote:
I find it amazing that I both ignored it and quoted it at the same time!
Okay, here's the rest of my last post you ignored:

Secondly, I never stated that volatile changes incrementation into an atomic operation. I stated that x86 guarantees that a 32-bit store is atomic.

It's called a ring buffer and the algorithm is as old as dirt. It's described in many places, and I am neither the first nor the last person to implement it. It was invented by people much smarter than you and used by a person much smarter than you. Also that last person was named Jon`C.

No, really? It's sure a good thing you're here to tell me that, because I'm apparently stupid and never designed my code to return an error value in that case or anything. I definitely am not using my very simple high-speed ring buffer to route messages between variable-sized message queues or anything like that, because to do that I would have to realize that my fixed-size buffer can possibly become full.

...unfortunately, while that solution is "better", it is also slower.
2006-10-15, 5:31 PM #45
Originally posted by Isuwen:
No, I won it the moment he claimed I didn't know C++, and I dropped a boost::spirit based recursive descent parser on him.
No, I claimed you haven't made/released anything. Which is true. Sith 2 may not be finished, but at least the code is out there. If someone wants to finish it they can.

Now all you've released is a painfully-convoluted mess of nonsense uncommented* code, using a template metaprogrammed recursive-descent parser, when not only Bison would have been a more appropriate choice but it would be much easier to maintain.

Kudos, I suppose. You sure showed me.

Loser.

(* = edit for completeness. Jesus Christ, no comments at all.)
2006-10-15, 5:42 PM #46
Quote:
Except, as I stated, 'Thread B' cannot increment 'variable X' - only 'Thread A' can. On X86 a 32-bit store operation is guaranteed atomic, meaning that 'Thread A writes register F to variable X' will complete before 'Thread B loads variable X into register G'.

This is not the case on other systems: namely Alpha which only offers 16-bit granularity, and x86-64 (in 64-bit mode) which offers 32-bit granularity but a 64-bit size_t. My code is thread-safe
And yet, thread B could end up using either value of X: The volatile does not guarantee that thread B will not load X while thread A is modifying it, but only that thread A will immediatly write it back.

Quote:
Fortunately there is nothing in any of those constructors which can throw an exception. Which is, also, why I did not make my message queue class a template.

Assuming that your code will never be capable of throwing an exception is naive, and just asking for trouble later.

Quote:
1.) Don't need it.
2.) Doing that myself already.
3.) Where is the insurance against the STL vendor screwing up? For instance: http://www.dinkumware.com/vc_fixes.html
This is old, but Dinkumware periodically releases bug fixes for their STL implementation which are not made available for VC users. The STL is not 100% safe, my code is not 100% safe, your code is not 100% safe. Fortunately, unlike your code, mine is very simple so if there is an issue I'm going to find it before you will.

1) Rather, "Don't need it now."
2) You didn't have to in the first place.
3) The STL was written by experts familiar with the internal workings of the compiler, and has inumerably more users than your code; and therefore, many many chances to uncover any bugs it might contain.

Quote:
Okay, here's the rest of my last post you ignored:

Secondly, I never stated that volatile changes incrementation into an atomic operation. I stated that x86 guarantees that a 32-bit store is atomic.

It's called a ring buffer and the algorithm is as old as dirt. It's described in many places, and I am neither the first nor the last person to implement it. It was invented by people much smarter than you and used by a person much smarter than you. Also that last person was named Jon`C.

No, really? It's sure a good thing you're here to tell me that, because I'm apparently stupid and never designed my code to return an error value in that case or anything. I definitely am not using my very simple high-speed ring buffer to route messages between variable-sized message queues or anything like that, because to do that I would have to realize that my fixed-size buffer can possibly become full.

...unfortunately, while that solution is "better", it is also slower.


32 bit stores being atomic also doesn't make the modification thread-safe. They are an artifact of the architecture being 32bit. It would be absurd if the storage of a single machine word weren't atomic.

You needn't exaggerate: Dirt is very old. Whomever it was implemented and used by is irrelevant. I'm pointing out that I know what algorithm you are using, and how it works. (Plus, that article has a nice little diagram.)

So, when it fills up, does your writer thread spin until push returns true?

Actually, no, the CAS and CAS2 primitives can be implemented using the assembly intstructions cmpxchg and cmpxchg8b on x86 (And, actually, have to be in order to make the structure thread safe). The fact that the concurrency is handled by a single instruction is what makes that implementation fast.
Wikissassi sucks.
2006-10-15, 5:42 PM #47
Originally posted by JediGandalf:
What's wrong with making your own Queue? It's not exactly a difficult data structure to make.

It is a matter or whether or not it is worth reinventing the wheel. Why make a new Queue class if there is one available? In this case, the STL Queue did not satisfy the needs of Jon`C, so he made a new one.

Isuwen, I hate to take sides, but your code is much more difficult to read. I'm also not a huge fan of Boost, since they don't guarantee any sort of compatibility between versions and their libraries are a convoluted mess.
[This message has been edited. Deal with it.]
2006-10-15, 5:47 PM #48
Originally posted by kyle90:
Whichever side Jon'C is on in a debate, wins automatically. Thus the ultimate debating strategy is simply to align one's self with Jon'C's opinion. Thankfully this is not hard to do because in general the other side is stupid.

.
free(jin);
tofu sucks
2006-10-15, 5:51 PM #49
Quote:
No, I claimed you haven't made/released anything. Which is true. Sith 2 may not be finished, but at least the code is out there. If someone wants to finish it they can.

Now all you've released is a painfully-convoluted mess of nonsense uncommented* code, using a template metaprogrammed recursive-descent parser, when not only Bison would have been a more appropriate choice but it would be much easier to maintain.

Kudos, I suppose. You sure showed me.

Loser.

(* = edit for completeness. Jesus Christ, no comments at all.)


I have a rather lot of publicly available code, actually... and what I posted here isn't even part of it. And, heck, some of it's actually used by other people.

Now, we can argue about wether Bison would have been better: Well, no. Bison is another build step; clearly I would prefer to have it all contained (and hidden) right there in the source file. Afterall, that's what boost::spirit was designed for.

I won't defend my lack of comments, because I don't comment. But I read your comments, and almost all of them just repeat what the code says.
Wikissassi sucks.
2006-10-15, 5:54 PM #50
I think this is funny.

Mostly because the only coding I ever do is actionscript (and im not good at it) but Jons code is easier to understand...
[01:52] <~Nikumubeki> Because it's MBEGGAR BEGS LIKE A BEGONI.
2006-10-15, 6:00 PM #51
Originally posted by Isuwen:
And yet, thread B could end up using either value of X: The volatile does not guarantee that thread B will not load X while thread A is modifying it, but only that thread A will immediatly write it back.
Why are you so stuck on the concept of a volatile? I have explained exactly what the volatile keyword does in several occasions in this thread, but you keep obsessing over it.

READ THIS BECAUSE YOU ARE TOO DUMB TO FIND IT IN THE OTHER 8 PLACES IN THIS THREAD: I know exactly what volatile does. I know exactly how the compiler will treat a volatile variable. I know it has absolutely nothing to do with anything except guaranteeing that the variable will not be cached by the optimizer. <- READ THAT BECAUSE YOU ARE TOO DUMB TO FIND IT IN THE OTHER 8 PLACES IN THIS THREAD

It does not matter if thread B uses an old value for X because the old value will result in no action being taken.

Quote:
Assuming that your code will never be capable of throwing an exception is naive, and just asking for trouble later.
No it isn't. This is low-level backend code I have not touched since last year. There is nothing below this class that can throw an exception. Nothing below this class even uses the new operator.

Quote:
1) Rather, "Don't need it now."
I will never need it.

Quote:
2) You didn't have to in the first place.
But I did.

Quote:
3) The STL was written by experts familiar with the internal workings of the compiler, and has inumerably more users than your code; and therefore, many many chances to uncover any bugs it might contain.
Fortunately I am the only user of my code, I know exactly how it works, and my code is called 1440 times a second. I'm waiting for your point.

Quote:
32 bit stores being atomic also doesn't make the modification thread-safe. They are an artifact of the architecture being 32bit. It would be absurd if the storage of a single machine word weren't atomic.
The modification is thread-safe for exactly the same reason any other semaphore ever works.

On multiprocessor Alpha machines, machine word stores are not atomic.

Quote:
You needn't exaggerate: Dirt is very old. Whomever it was implemented and used by is irrelevant. I'm pointing out that I know what algorithm you are using, and how it works. (Plus, that article has a nice little diagram.)
Tower of Hanoi old then.

Quote:
So, when it fills up, does your writer thread spin until push returns true?
No.

Quote:
Actually, no, the CAS and CAS2 primitives can be implemented using the assembly intstructions cmpxchg and cmpxchg8b on x86 (And, actually, have to be in order to make the structure thread safe). The fact that the concurrency is handled by a single instruction is what makes that implementation fast.
That's super. So can mine.
2006-10-15, 6:04 PM #52
Originally posted by Isuwen:
I have a rather lot of publicly available code, actually... and what I posted here isn't even part of it. And, heck, some of it's actually used by other people.
If your code is so great and publicly available, how about your link to some of it?

Quote:
Now, we can argue about wether Bison would have been better: Well, no. Bison is another build step; clearly I would prefer to have it all contained (and hidden) right there in the source file. Afterall, that's what boost::spirit was designed for.
Template metaprogramming is an afront to the Lord.

Quote:
I won't defend my lack of comments, because I don't comment. But I read your comments, and almost all of them just repeat what the code says.
But... that's what comments are supposed to do.

Admittedly a number of my comments in that code are unneccessary (like "default destructor"), but your complete lack of comments is pretty damn retarded.
2006-10-15, 6:27 PM #53
Quote:
Why are you so stuck on the concept of a volatile? I have explained exactly what the volatile keyword does in several occasions in this thread, but you keep obsessing over it.
You brought it up as a reason why you could not use a dequeue.
Quote:
No it isn't. This is low-level backend code I have not touched since last year. There is nothing below this class that can throw an exception. Nothing below this class even uses the new operator.

I will never need it.

But I did.

Fortunately I am the only user of my code, I know exactly how it works, and my code is called 1440 times a second. I'm waiting for your point.


So, your code is perfect and can never fail, because it was written by you?

Quote:
The modification is thread-safe for exactly the same reason any other semaphore ever works.

Semaphores rely on hardware support for atomic increment/decrement operations. A multi-tasking OS can simulate the support by pausing the task switching.

Quote:
On multiprocessor Alpha machines, machine word stores are not atomic.
They are if both threads are running on the same processor. It's only an issue when multiple processors write to the same location at the same time. The hardware serializes memory access at the byte level instead.

Quote:
Tower of Hanoi old then.
Okay, that's pretty old.

Quote:
Quote:
So, when it fills up, does your writer thread spin until push returns true?
No.
Does it just forget about the message? Is it lost? Does the system abort? What happens?

Quote:
That's super. So can mine.
So can yours what?

Quote:
If your code is so great and publicly available, how about your link to some of it?
Sure! I wrote a preprocessor addon for the scripting language AngelScript. http://www.angelcode.com/angelscript/extras.asp Ignore the ugly HTML, it's just a dump of my readme file.

Quote:
Template metaprogramming is an afront to the Lord.
Then I have sinned.

Quote:
But... that's what comments are supposed to do.
Absolutely not! http://en.wikipedia.org/wiki/Comment
Wikissassi sucks.
2006-10-15, 6:34 PM #54
[http://www.immolationism.com/images/15.gif]
Quote Originally Posted by Chaz Ghostle
some gay men prefer to have partners with smaller, softer bodies[. . .]It really all comes down to what you like.
2006-10-15, 6:43 PM #55
Originally posted by Isuwen:
You brought it up as a reason why you could not use a dequeue.
No, I brought it up as something I would have to do in order to use one.

Quote:
So, your code is perfect and can never fail, because it was written by you?
No. However, if my code does fail, I will be able to fix it.

Quote:
Semaphores rely on hardware support for atomic increment/decrement operations. A multi-tasking OS can simulate the support by pausing the task switching.
Correct: other semaphores work because an update to the semaphore is atomic. I'm glad we agree.

Quote:
They are if both threads are running on the same processor. It's only an issue when multiple processors write to the same location at the same time. The hardware serializes memory access at the byte level instead.
This is what I said earlier in the thread. And, actually, the hardware serializes memory access at the 16-bit level.

Quote:
Okay, that's pretty old.
Not the... you know... creation story, but the mid-1800s mathematician old.

Quote:
Does it just forget about the message? Is it lost? Does the system abort? What happens?
The message is not removed from the queue.

Quote:
So can yours what?
Be implemented much faster using x86 assembly, just like most other programs.

Incidentally, your argument that the algorithm is much faster than mine is because it can be implemented in a single instruction (cmpxchg) is flawed. How many cycles does that instruction take? 3? Throw that on a multiprocessor machine and suddenly your operation isn't atomic.

Quote:
Sure! I wrote a preprocessor addon for the scripting language AngelScript. http://www.angelcode.com/angelscript/extras.asp Ignore the ugly HTML, it's just a dump of my readme file.
Fantastic.

I'm on my second scripting language. But your plugin is good too.

Quote:
Then I have sinned.
Pedophilia is a sin too FYI.

Yeah, we can argue over "proper use" of a comment all night, but everybody universally agrees that your complete lack of comments is stupid.
2006-10-16, 3:33 AM #56
Quote:
Incidentally, your argument that the algorithm is much faster than mine is because it can be implemented in a single instruction (cmpxchg) is flawed. How many cycles does that instruction take? 3? Throw that on a multiprocessor machine and suddenly your operation isn't atomic.
Actually, it being atomic is the very reason for it's existence.

Quote:
Pedophilia is a sin too FYI.
WTF is wrong with you? I ignored you the first time you did this because I thought you were just being a tard. You going to make more baseless claims, or go surf kiddie porn sites manufacturing evidence?
Wikissassi sucks.
2006-10-16, 8:11 AM #57
Originally posted by Isuwen:
Actually, it being atomic is the very reason for it's existence.


cmpxchg is only atomic on single processors. Multiprocessor code requires a lock prefix, which is substantially slower.
2006-10-16, 8:34 AM #58
When Jon'C does a push-up, he pushes the earth down. [/SIZE]
Was cheated out of lions by happydud
Was cheated out of marriage by sugarless
2006-10-16, 8:51 AM #59
When Jon'C sneezes it is a funtion used to leech extra smart from his brain.

This smart is quickly replaced.

Also, Jon'C never sneezes because he has an infinite capacity of smart.
2006-10-16, 9:07 AM #60
Reasons not commenting is :downs:

Situation 1: Open Source

You release your project (finished or not finished). Another person would like to modify or improve a portion of the code. He jumps in the file, and attempts to find the function he is looking for. He starts skimming.

Tell me, which is faster to skim? A bunch of code using archaic function names and made up names used by the original programmer, mixed into a crapload of operations, or a single comment line that states "This function grabs the mouse"?

Situation 2: Time flies...

You put a project on hold, for whatever reason. A year later, you find it sitting in a corner of your hard drive. You decide to finish it, and crack it open. You find an error, and locate the function causing it in the code. But now you're staring at the function, wondering just what in the bloody hell this function was supposed to do in the context of the entire program. You spend hours tracking down all the linked custom functions and variables to find out what you were doing with this function so you could fix it without breaking it.

Or you could have just written "This function calculates the FPS being obtained by the renderer." and realized it wasn't terribly important in the first place.

Situation 3: What was that input?

You wrote your own function an hour or so ago to handle keypresses. Now you're ready to use that function later in the code. But alas, you have forgotten the syntax for your function. Was the first value supplied the status of the key, or was it the key pressed?

Now, you could go back to the function and burn through it to discover the proper order and expected type (were you using characters, or did you need to convert to ASCII number first?), or you could read your handy cheatsheet comment at the top that gave a good example of what the function expects.

But hell, what do I know, I only program PHP and HTML. :psyduck:
12

↑ Up to the top!