Your rw-mutex has way too much overhead for read access. You don't need to
acquire a lock (e.g., WriterMutex) in your ReadEnter/Leave functions. Here
is an example of how you can do it:
http://groups.google.com/group/comp.programming.threads/msg/cfdc3cec444b5544
Also, what are your TCriticalSection::Check/Count functions used for?
Functions like that are usually a sign of poor design. The results you get
from those functions are not coherent wrt the current state of the lock at
any one time.
Your Get function has a race-condition. Why are you mutating the queue under
read-access? Ouch!
Oh my.... I hope that the code you posted is not used in any product!
Why do did you fail to check any return values?????
Double Ouch!!
:^(...
Oh really? You don't have to check for errors?
> Maybe you dont' understood OOPS and local scoping.
Your completely missing the point.
> If you want to show the problem, please do.
>
> TCriticalSectionGrabber grab(WriterMutex);
> WaitForSingleObject(ReadingOk, INFINITE);
> if (InterlockedIncrement(&Readers) == 0) {
> WaitForSingleObject(ReadingActiveSemaphore, INFINITE);
> }
What if WaitForSingleObject failes? Huh? Please explain!
> Don't worry. You got me curious. I am currently writing an isolated tester
> and if I have time, I going to compare by checking out your own unreadable
> code. You chose to be rude with the wrong guy.
If you think that pointing out bugs in your code is rude, then so be it.
> But even then, if there is something wrong, I'll admit it. But I have to
> see for myself. :-)
Most rw-mutexs out there have race-conditions.
> As a starting point, where specifically is the race conditions and can you
> cite an example?
The only problem I can see right off the bat with your implementation is you
failed to check any return values.
Its experimental. I am drawing up a proof and plan on proposing it for the
Boost Library pretty soon. Read the thread named:
"A fast-pathed rw-mutex algorithm for Boost..."
here:
http://lists.boost.org/Archives/boost/2006/10/index.php
>> Also, what are your TCriticalSection::Check/Count functions used for?
>> Functions like that are usually a sign of poor design. The results you
>> get from those functions are not coherent wrt the current state of the
>> lock at any one time.
>
> Baloney.
I will ask again. What do you use those functions for?
> The fact our products are used by hundreds of thousands of customer for
> nearly 12 years under 365x24x7 operating conditions, uncategorically
> proves without the shadow of a double the HIGH QUALITY of the RPC
> server/client system with absolutely NO multi-threads contention
> conflicts.
That means nothing to me as there are a lot of products with race-conditions
that may never get to manifest themselves.
> Now, if you want to show HOW we can run into a problem with an example, I
> am willing to listen. I'm too old to have regrets and have no problem is
> there is a potential hidden issue. But I am not going to take YOUR blurted
> out claims that your CODE is any better or worst.
My rw-mutex fast-paths the read-access, yours doesn't. That's fine. I wanted
to point out that you can do a fast-path.
> You have to prove it.
I can prove it with the mathematical proof I am drawing up? Can you show me
the proofs for you code?
[...]
With all that experience, how did you make this newbie mistake:
http://groups.google.com/group/comp.programming.threads/msg/f1f24106d6dcaa33
?
I am not trying to be rude. If I come across that way, well, I am truly
sorry. I simply had to point out that bug, and all the others wrt not
checking return values.
Sorry about that.
Ok, I see what is going on here now.
You don't understand OOPs concept of local scoping and class
construction overloads.
There is no CONTENTION or CLOBBERING in this code. It is a THING OF BEAUTY!
When the eventQ.Get() is called, it uses the class instance:
TReaderGrabber grab(Mutex);
This will instantiate a local scope which means NO ONE will be allowed
pass this point until the local scope is lost, i.e, exiting the
function. During the TReaderGrabber construction, it will create a WRITE
LOCK using this constructor overload:
TReaderGrabber(TReaderWriter &rw): RW(rw) { RW.ReaderEnter(); }
See the :RW(rw) ???
That will promote the critical section lock that will stop the block any
writing.
I will not go any futher on this as it was now obvious it was innocent
clear issue that you thought you wrote a better RW cped than anything
else out there, but you didn't study my classes and lacked the
understanding on how it worked. The fact you ask "checking return
values" clearly shows you don't underclass the class.
But if you wish to continue to PROVE there is something wrong, then by
all means, please do, I am all ears (or eyes <g>). But you have to
PROVE it.
Here is proof it works greate with 10 random threats BANGING away adding
the the FIFO queue, while the main threads flushes the queue. Use
this to show there is a problem. You will see there is not.
// File: D:\wc6beta\testqueue.cpp
#include <stdio.h>
#include <afx.h>
#include <afxtempl.h>
#include <process.h>
#include <conio.h>
#include "critsect.h"
const DWORD MAX_THREADS = 10;
HANDLE ShutdownEvent = NULL;
DWORD IndexCounter = 0;
/* Macro to get a random integer within a specified range */
#define getrandom( min, max ) (( rand() % (int)((( max ) + 1 ) - ( min
))) + ( min ))
typedef struct tagTWCFWatchEvent {
DWORD index;
DWORD area;
DWORD action;
char filename[256];
} TWCFWatchEvent;
class CWCFWatchQueue : public CList< TWCFWatchEvent, TWCFWatchEvent>
{
public:
CWCFWatchQueue() {active = FALSE;}
void Add( const TWCFWatchEvent &o )
{
TWriterGrabber grab(Mutex);
AddHead( o );
}
BOOL Get(TWCFWatchEvent &o)
{
TReaderGrabber grab(Mutex);
if (IsEmpty()) return FALSE;
o = RemoveTail();
return TRUE;
}
private:
TReaderWriter Mutex;
BOOL active;
};
CWCFWatchQueue feQ;
//-------------------------------------------------------
// MAIN
//-------------------------------------------------------
BOOL CheckShutdownEvent(DWORD msecs = 0)
{
return (WaitForSingleObject(ShutdownEvent, msecs) == WAIT_OBJECT_0);
}
void EventThread(void *p)
{
while(1) {
if (CheckShutdownEvent(getrandom(1, 500))) {
break;
}
TWCFWatchEvent fe = {0};
fe.index = InterlockedExchangeAdd((long *)&IndexCounter,1);
fe.area = getrandom(1, 1000);
fe.action = getrandom(1, 10);
feQ.Add(fe);
}
_endthread();
return;
}
BOOL do_queue(const BOOL bProcess = TRUE)
{
TWCFWatchEvent fe;
DWORD nTotal = feQ.GetCount();
DWORD nProcessed = 0;
while (feQ.Get(fe)) {
//printf("i: %4d | area: %3d act: %5d fn: [%s]\n",
// fe.index,fe.area,fe.action,fe.filename);
// Sleep(1); // GO AHEAD! SLOW IT DOWN
nProcessed++;
}
printf("- Queue count: %5d | Processed: %5d\n",nTotal, nProcessed);
return FALSE;
}
BOOL do_watch()
{
printf("* Starting Event Queue Processor (ESCAPE to exit)\n");
int iQueryDelay = 1000;
int iKeyDelay = 500;
int ticks = GetTickCount();
while (1) {
Sleep(iKeyDelay);
if (kbhit()) {
int ch = getch();
if (ch == 27) return TRUE; // exit process if started with
"/start"
if (ch == '/') return FALSE; // stay in cmd
}
if ((GetTickCount()-ticks) >= DWORD(iQueryDelay)) {
if (feQ.GetCount()) {
do_queue(TRUE);
}
ticks = GetTickCount();
}
}
return FALSE;
}
void main(char argc, char *argv[])
{
int i;
srand( (unsigned)GetTickCount()*GetCurrentThreadId()); /* Seed
randomizer */
ShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE hThreads[MAX_THREADS] = {0};
printf("+ Creating %d threads......\n", MAX_THREADS);
for (i=0; i <MAX_THREADS; i++) {
hThreads[i] = (HANDLE)_beginthread(EventThread, 0, NULL);
}
do_watch();
printf("+ Starting Shutdown......\n");
SetEvent(ShutdownEvent);
//-------------------------------------------------------
// wait for completion
//-------------------------------------------------------
while
(WaitForMultipleObjects(MAX_THREADS,hThreads,TRUE,1)==WAIT_TIMEOUT) {
if (kbhit() && getch() == 27) break; // sanity escape hatch
}
printf("* Cleanup\n");
printf("* Successful Shutdown\n");
CloseHandle(ShutdownEvent);
}
--
You should read up on OOPS class constructors, inlining and initializers.
This is especially true because it offers compiled operation that is
ideal for binding, efficiency, optimization which is ideal for
synchronization design models.
There are numerous articles on the subjects for your to explore.
--
HLS
I still think you have an error. Please bear with me here:
class CWCFWatchQueue : public CList< TWCFWatchEvent, TWCFWatchEvent>
{
public:
CWCFWatchQueue() {active = FALSE;}
void Add( const TWCFWatchEvent &o )
{
TWriterGrabber grab(Mutex);
AddHead( o );
}
BOOL Get(TWCFWatchEvent &o)
{
TReaderGrabber grab(Mutex);
if (IsEmpty()) return FALSE;
o = RemoveTail();
return TRUE;
}
private:
TReaderWriter Mutex;
BOOL active;
};
IMO, the Get function is in error. Taking a readlock does not stop multiple
threads from calling RemoveTail concurrently. How is RemoveTail implmented?
You are not making correct use of a rw-mutex. You MUST ensure that there
will be no more than a SINGLE thread access this function as is.
To fix your code:
class CWCFWatchQueue : public CList< TWCFWatchEvent, TWCFWatchEvent>
{
public:
CWCFWatchQueue() {active = FALSE;}
void Add( const TWCFWatchEvent &o )
{
TWriterGrabber grab(Mutex);
AddHead( o );
}
BOOL Get(TWCFWatchEvent &o)
{
TWriterGrabber grab(Mutex);
// you MUST take exclusive access here because you
// call RemoveTail which mutates the list. Mutations are
// for writers to perform only!
if (IsEmpty()) return FALSE;
o = RemoveTail();
return TRUE;
}
private:
TReaderWriter Mutex;
BOOL active;
};
There. Now it works.
I know all about using helper classes to acquire and release synchronization
object.
So, your saying that only a SINGLE thread will ever exist in the following
code at any one time:
{
TReaderGrabber read_lock(...);
// right here?
}
Of so, that's not how a rw-mutex works.
[...]
You are performing a mutation to a shared data-structure under a read-lock.
You call RemoveTail is a queue under a read-lock. This allows more than one
thread to call RemoveTail concurrently. That's an error.
You call RemoveTail in a queue implmentation under a read-lock.
> thread to call RemoveTail concurrently. That's an error.
This violates POSIX rules. You cannot allow a thread to take read access
from a rw-mutex and then mutate the shared data-structure that its
protecting.
Here is a clear-cut example your race-condition "Pops":
Thread A
--------------------------------
void Add( const TWCFWatchEvent &o ) {
1: TWriterGrabber grab(Mutex);
2: AddHead( o );
3: } /* done */
Threads B & C
--------------------------------
BOOL Get(TWCFWatchEvent &o) {
1: TReaderGrabber grab(Mutex);
2: if (IsEmpty()) return FALSE;
3: o = RemoveTail();
4: return TRUE;
5: } /* done */
Execution Pattern
--------------------------------
Thread A Thread B Thread C
-----------------------------------------------------------------
1: A1
2: A2
3: A3 B1 C1
4: B2 C2 (note that queue is not empty...)
*5: B3 C3 (here is the bad place!)
-----------------------------------------------------------------
Line 5 in the execution pattern allows B3 and C3 to access RemoveTail
concurrently. This is a race-condition. Period.
I am afraid the problem you are facing with is no OOP but concurrency
one by nature.
One problem with your code is that it is not a readers and writers
problem since you do not read the queue but remove elements from it,
hence the apparent read operation "RemoveTail()" is not a pure read
operation but a write one.
The other concurrency problem lies in your "Get()" method. In a
concurrent system an operation should not return if the conditions are
not fulfilled but rather the operation must be delayed.
Finally, your test does not prove anything. Just insert a delay around
the "Add()" operation and the report about "nProcessed" will be false.
Best Regards,
Szabolcs
THERE IS MANY WRITER, BUT ONLY ONE READER!!! ALL WRITER THREADS ARE
CONTROLLED, BUT ONLY ONE THREAD TO ACCESS THE READER. NOW IF WE WERE
TALKING ABOUT MULTIPLE READERS, THEN YOU WOULD NEED TO SYNC THE READING TOO!
PLEASE SEE THE CODE AND UNDERSTAND IT!!
NOW ENUF! OK???
--
HLS
That is true. Its a destruction. However, it appears that design point
was lost that is is a MULTIPLE WRITER, SINGLE READER design concept.
Thus only one READER can destroy. and all WRITE activity is
sychronizations, never dual writers and more importantly, it is also
BLOCKED during READING.
> Finally, your test does not prove anything. Just insert a delay around
> the "Add()" operation and the report about "nProcessed" will be false.
I don't think you followed the code right.
The CheckShutdownEvent() has a random delay to it. Did you notice that?
But again, you missed the point of the design here. Fast adding to the
queue, to allow a 2nd thread to process it that is not restrictied in
its processing time.
As my post indicated, if the QUEUE was building too fast, and additional
reader/procesing threads can be added.,
In this case, you are 100% correct, a sychronization would have to be
added to the Get() RemoveTail() code. Absolutely. In this case, it
wouldn't bother with the Reader/Writer Grabbers, but instead directly
using a TCriticalSection instance:
class CWCFWatchQueue : public CList< TWCFWatchEvent, TWCFWatchEvent>
{
public:
void Add( const TWCFWatchEvent &o )
{
TCriticalSectionGrabber grab(Mutex);
AddHead( o );
}
BOOL Get(TWCFWatchEvent &o)
{
TCriticalSectionGrabber grab(Mutex);
if (IsEmpty()) return FALSE;
o = RemoveTail();
return TRUE;
}
private:
TCriticalSection Mutex;
};
Otherwise, for the FAST MULTIPLE WRITER, SINGLE READER design as the OP
needs the Reader/Writer Grabber logic I posted is 100% perfect.
Anything else?
--
HLS
[...]
You got that totally backwards. Think about it... A read-writer mutex allows
for:
Multiple-Readers, but only one Writer.
Please read:
http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_rwlock_rdlock.html
then read:
http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_rwlock_wrlock.html
Why use a rw-mutex when there is only one reader? You are totally misusing a
rw-mutex.
[...]
Szabolcs is correct in that you are performing a write operation under
read-access which is busted by default.
Multiple-Writer Single Reader should use a normal mutex, not a rw-mutex. Why
in the heck would you use a rw-mutex when there is only going to be a single
reader???
Please explain in great detail!
--
HLS
Look, you need to stop.
You first said the class was wrong. Which you were proven wrong showing
you lack understanding of OOPS C/C++ construction and local scoping
concepts.
Then you went into great pain "OUCH!" and sprewed baloney about how the
Get() logic was wrong and getting clobbered with writes, and that all my
products were fundamemtally wrong. You were shown to be wrong on both
counts again.
Then you I PROVED to you it works fine with real code, and you then
tried to TWIST IT into it is note by making it different design. You
were shown how you didn't understand the design and once again wrong.
I told you if there was MULTIPLE READERS, you could use a CRITICAL
SECTION instead. That wasn't enough for you.
Now you want to know why I used a Reader/Writer in the first place.
Because you CAN, you MORON!!
Lets take a look at your code which YOU SAW it PERFECT RW LOGIC, YET you
have no field and production experience at all to prove it.
Oh never mind, your code is too UGLY to follow. You need to CHECK
return values in your implementation, OUCH, now that is POOR!!
--
HLS
>
> Then you went into great pain "OUCH!" and sprewed baloney about how the
> Get() logic was wrong and getting clobbered with writes, and that all my
> products were fundamemtally wrong. You were shown to be wrong on both
> counts again.
>
> Then you I PROVED to you it works fine with real code, and you then tried
> to TWIST IT into it is note by making it different design. You were shown
> how you didn't understand the design and once again wrong.
>
> I told you if there was MULTIPLE READERS, you could use a CRITICAL SECTION
> instead. That wasn't enough for you.
You are totally missing the entire point. When you have multiple readers you
use a reader writer solution. When you have single reader why use a rw-mutex
at all? You don't seem to want to understand that.
> Now you want to know why I used a Reader/Writer in the first place.
>
> Because you CAN, you MORON!!
>
> Lets take a look at your code which YOU SAW it PERFECT RW LOGIC, YET you
> have no field and production experience at all to prove it.
You know not of what you speak sir. We are a group of multi-threading
experts here on comp.programming.thread; Please do your homework.
> Oh never mind, your code is too UGLY to follow. You need to CHECK return
> values in your implementation, OUCH, now that is POOR!!
Please show me where I failed to check return values? This is your problem
not mine. You failed to check return values which means your code is
definitely NOT production quality:
http://groups.google.com/group/comp.programming.threads/msg/028de3c025be8ffa
I am still waiting for an answer to the following question concerning your
rw-mutex implementation:
> TCriticalSectionGrabber grab(WriterMutex);
> WaitForSingleObject(ReadingOk, INFINITE); if
> (InterlockedIncrement(&Readers) == 0) {
> WaitForSingleObject(ReadingActiveSemaphore, INFINITE); }
What if WaitForSingleObject fails for whatever reason? Huh? Please explain!
Please answer that question. Then tell your customers that this code could
hit a failure condition in the WaitForSingleObject calls and go on its merry
way corrupting the data-structure all the way down.
Stop top-posting please.
You show your ignorance when you use a rw-mutex in a scenario that has
multiple-writers and only a single reader. Enough said on that point. Please
by a threading book and learn why I am correct on this point and you are
wrong:
http://www.amazon.com/Programming-POSIX-Threads-David-Butenhof/dp/0201633922
Read that and come back and tell us what you have learned.
Your right, however, "Pops" uses a rw-mutex to protect a single reader. I
don't think I have ever seen any programmer do this.
<Sarcaism>
That is pure genius. I mean the whole reason a reader-writer solution exists
is to allow for only a single reader to access the data-structure!
</Sarcaism>
"Pops" is completely confused on this point I'm afraid. Perhaps we can teach
him how to correctly use reader writer solutions.
<More Sarcaism>
The first thing you need to know is that you don't need one if your only
going to be using a single reader! Wow.
</More Sarcaism>
> The other concurrency problem lies in your "Get()" method. In a
> concurrent system an operation should not return if the conditions are
> not fulfilled but rather the operation must be delayed.
Indeed. "Pops" has to rename this function to "TryGet()" or something.
> Finally, your test does not prove anything.
Right.
No, I did not notice that. Please replace that thing with a constant
delay of, let us say, one minute and see what happends to your test
results.
Just try it please and report the result.
Best Regards,
Szabolcs
Ok Chris,
For the sake of the newsgroup. Your right. I was wrong. My code sucks,
I don't know what I am talking about, my products are flawed. I will
never post any code again because its sucks. I need to buy books again.
Your code is perfect and we all use your R-W "Fast-Paths" technology.
Can I use it? You are good, friendly and write good too. Need a job
in sunny South Florida? I need someone like you to fix our code up.
Thanks for pointing out my mistakes. You can stop writing now.
Ciao
--
HLS
I don't think I missed the point. You have constructed a class with
two operations believing that one operation is a writing and the other
is a reading one in nature. That is why you were trying to apply the
readers and writers pattern to it. Your assumption is not correct,
since the supposedly read operation ("RemoveTail()") also modifies the
data structure, i.e. it is effectively a writing operation. Hence you
cannot apply the read-write lock in this case.
So simple is that.
Best Regards,
Szabolcs
>
> Then you went into great pain "OUCH!" and sprewed baloney about how the
> Get() logic was wrong and getting clobbered with writes, and that all my
> products were fundamemtally wrong. You were shown to be wrong on both
> counts again.
>
> Then you I PROVED to you it works fine with real code, and you then tried
> to TWIST IT into it is note by making it different design. You were shown
> how you didn't understand the design and once again wrong.
>
> I told you if there was MULTIPLE READERS, you could use a CRITICAL SECTION
> instead. That wasn't enough for you.
You are totally missing the entire point. When you have multiple readers you
use a reader writer solution. When you have single reader why use a rw-mutex
at all? You don't seem to want to understand that.
> Now you want to know why I used a Reader/Writer in the first place.
>
> Because you CAN, you MORON!!
>
> Lets take a look at your code which YOU SAW it PERFECT RW LOGIC, YET you
> have no field and production experience at all to prove it.
You know not of what you speak sir. We are a group of multi-threading
experts here on comp.programming.thread; Please do your homework.
> Oh never mind, your code is too UGLY to follow. You need to CHECK return
> values in your implementation, OUCH, now that is POOR!!
Please show me where I failed to check return values? This is your problem
Huh? But that is unrealistic design! You want a 1 minute WFSO wait on
the shutdown kernel object?
How silly. Why? Why don't you just compile it and do it yourself to
prove whatever point you are making?
Ok, I will fancy you, but come on, you are quickly showing that I am
dealing with inexperience kids here with limited design experience.
But I changed it to this:
void EventThread(void *p)
{
while(1) {
if (CheckShutdownEvent(1getrandom(1, 500))) {
break;
}
Sleep(1000*60); // <------- PER SILLY REQUEST!
TWCFWatchEvent fe = {0};
fe.index = InterlockedExchangeAdd((long *)&IndexCounter,1);
fe.area = getrandom(1, 1000);
fe.action = getrandom(1, 10);
feQ.Add(fe);
}
_endthread();
return;
}
Ok, started, la, la, la, la, twiddling fingers, picking nose, waiting
for a minute... I have no clue what you EXPECT to happen.
WOW! WAIT 10 random Writers, 10 Single reader reads! No data clobber,
no GPFs!
ok Waiting for the next minute..... Same thing.
Come on fellas! This is getting really ridiculous, and this is the so
called comp.programming.thread "Multi-Threading Expert" forum?
Come on, atleast make some sense please.
I think you are looking for some way for the single reader thread to get
clobbered?
Maybe I show slow down the reading? Increase the # of threads?
Ok, lets use 20 writer threads, 1 single reader, no SILLY delay in the
writer and 1 quantum delay in the reader. This will be VERY VERY
interesting, I expect that QUEUE to build up fast!
Yup sure enough, queue was climbing fast. The reader can't be
artificially be slowed down, but it also tells ya that you will need
multiple readers which was ALREADY stated from the get-go and it was
already agreed this will required a reader sync.
All I am seeing here is a lack of experience in "Applied Multi-threaded
Design Models."
What are you trying to prove here?
The only legitimate compliant here is the usage of the MFC CList class.
No doubt, a better queue can be designed for PURE Multi-Reader
grabber designs. Need me to show you guys how?
---
HLS
Several Professors, Intel and Sun have both written articles that make
reference to my work:
http://groups.google.com/group/comp.programming.threads/browse_frm/thread/205dcaed77941352
I won First Round of Suns CoolThreads Contest:
https://coolthreads.dev.java.net/
https://coolthreads.dev.java.net/servlets/ProjectForumMessageView?messageID=11001&forumID=1797
I specialize in state-of-the-art virtually zero-overhead synchronization
algorithms. I have a fairly well respected reputation around here. I found
several errors in your code. I HAVE to point it out to others. You say your
stuff is used in high-quality products, yet to fail to check any error codes
from any of your Win32 API calls. If I were you I would correct the bugs in
your code and redistribute the binaries to all of your customers free of
charge. Other than that, well, you put code like that in production code,
and make ignorant statements like, and let me quote here:
Chris Thomasson Wrote:
Why did you fail to check any return values?????
----------------------------
Pops Replied:
"Because you don't have to."
----------------------------
Chris Thomasson Wrote:
> TCriticalSectionGrabber grab(WriterMutex);
> WaitForSingleObject(ReadingOk, INFINITE); if
> (InterlockedIncrement(&Readers) == 0) {
> WaitForSingleObject(ReadingActiveSemaphore, INFINITE); }
What if WaitForSingleObject fails for whatever reason? Huh? Please explain!
----------------------------
"Pops" Has no answer as of yet!
----------------------------
well, I would fire you on the spot if I was your boss! Seriously.
Well, if you provide a code that I can compile I would like to play
with it. Please provide a compilable code.
Besides, do not say that it is silly, since in concurrent programming
you must design your code so that it should be correct even if there
is a dime delay of even one year between any two operations.
Best Regards,
Szabolcs
Yes and no.
Grant it, the MFC CList is not ideal here for a reader/writer design. I
used it as a QUICK queue for the OP with the design intent for SINGLE
WRITER and SINGLE READER thread design.
But that wasn't the original whining done here. First the class itself
was flawed which was wrong due to lack of understanding of class
constructions and local scoping, and because of that lack of
understanding the there was a local clobber by the Add()/Get() logic!
Wrong again.
The reason I naturally use a reader/writer logic because it a IDEAL for
this type of design, it is very similar bucket brigade concept in
Telelcommunicatons flow control concepts.
The issue is my simplicity in throwing in a MFC CList for the FIFO, and
the only real issue is how the RTL handles the doubled linked list - it
is thread ready? Probably not.
But the type of design in question, there is ABSOLUTELY no problem with it.
Another approach, less ideal, yet improves in the reader/writer idea
under a MULTIPLE reader approach is as so:
BOOL Get(TWCFWatchEvent &o)
{
TReaderGrabber grab(Mutex);
{
TCriticalSectionGrabber grab(csMutex);
if (IsEmpty()) return FALSE;
o = RemoveTail();
}
return TRUE;
}
private:
TReaderWriter Mutex;
TCriticalSection csMutex;
What you doing here is allowing as MANY readers as possible into the
local scope, which moves into a Critical Section scope.
The idea is akin to a CLUB bouncer, allowing 5-10 people in at a time
and at the cashier, they all pay one at a time.
You can also use a circular buffer, but this will require upfront logic
on the boundary conditions for the writer - the PUMP.
So please fellas, you are talking to the wrong person with this silly
stuff. To prove what? That you are smarty than me and the code is wrong?
Well, that hasn't been shown at all and I find it really funny that you
MULTI-THREADING EXPERTS in that "other forum" are all gun happy to
jump on some coding specifics but lack the expertise to provide an
application solution to the original poster. Where is your expertise there?
--
HLS
--
HLS
You kidding right? And you are an expert?
Well, the critsect.h was posted separated, cut and paste that to
critsect.h and then compile the posted testqueue.cpp code with the
following line:
cl testqueue.cpp /W3 /GX /MD /D "_AFXDLL"
> Besides, do not say that it is silly, since in concurrent programming
> you must design your code so that it should be correct even if there
> is a dime delay of even one year between any two operations.
First, there is no such thing as concurrent programming if you talking
single CPU. True concurrently does not clobber, as in RTOS systems.
What we have is pre-emptive context switching which is an EMULATION of
CONCURRENCY - that is what it is all about! Again, your talking to the
wrong fella here, spare me the rethoric.
Second, we are taking about PRACTICAL SOLUTIONS here ok? not something
that is going to DELAY for 1 year - what a waste of time! and even then,
it doesn't matter. I don't see how the 1 year delay relates to the issue.
--
HLS
Well, it is quite indifferent, as far as the readers and writers
pattern is concerned, what resource you use for reading and writing.
Can it be a CList or your own data structure, the important issue is
whether you protect the resource correctly.
Now, if you change the resource and you just protect it as if you were
reading it, it is a definite error in concurrent programming. It is an
error even if you did not experience it in your trial runs. Do not be
in illusion. If the error does not manifest itself in a trial and
error "testing", it does not mean that it is not there. A concurrent
program is non-deterministic. If you want to test it, you have to
eliminate non-determinism for the testing.
Best Regards,
Szabolcs
No, I am not kidding.
> Well, the critsect.h was posted separated, cut and paste that to
> critsect.h and then compile the posted testqueue.cpp code with the
> following line:
>
> cl testqueue.cpp /W3 /GX /MD /D "_AFXDLL"
You never published that piece of code on this forum
(comp.programming.threads) which you admire so much. Please be so kind
and copy it here as well.
If you want us to help you, please be patient.
Best Regards,
Szabolcs
Duh!
> Can it be a CList or your own data structure, the important issue is
> whether you protect the resource correctly.
DUH! You have not proved it was not PROTECTED! So what is your point?
> Now, if you change the resource and you just protect it as if you were
> reading it, it is a definite error in concurrent programming. It is an
> error even if you did not experience it in your trial runs. Do not be
> in illusion. If the error does not manifest itself in a trial and
> error "testing", it does not mean that it is not there. A concurrent
> program is non-deterministic. If you want to test it, you have to
> eliminate non-determinism for the testing.
Blah, blah, blah, you are not telling me anything I have already
forgotten. This is all kids stuff. All unknowns were removed in the
posted code! It was designed with 100% perfection for the purpose it was
done for!
Now where is the results of whatever you were trying to prove? Are you
going back that critsect.h was flawed or that the implementation was wrong?
As the saying goes, "Proof is in the pudding" otherwise, badly quoting
Dorothy Parker, lets "thrown this baloney into the waste basket with
force force!"
--
HLS
Are you sure about it?
I always thought I was writing concurrent programs when I solved the
problem with help of more co-operating processes and it is just some
particular circumstance whether it is executed on a single processor
or on multiple ones. As a matter of fact, it is indifferent to my
programs. In my experience my programs always ran on a single
processor as well as on multiple ones.
Do I miss some state of the art development?
Best Regards,
Szabolcs
>> You kidding right? And you are an expert?
>
> No, I am not kidding.
hmmmmmm, alert("expertise under suspicion!");
>
>> Well, the critsect.h was posted separated, cut and paste that to
>> critsect.h and then compile the posted testqueue.cpp code with the
>> following line:
>>
>> cl testqueue.cpp /W3 /GX /MD /D "_AFXDLL"
>
> You never published that piece of code on this forum
> (comp.programming.threads)
You boy chris did that. Not me! I posted in the Microsoft forum.
> which you admire so much.
Admire? ha! Its freaking code thats all! It works! and based on what I
see, I doubt you can do any better. If you have to ASK how to compile
posted code, geez, I am getting the feeling you are a GUI programmer and
don't have any clue about console compiling? Am I off base? You do
know how to open a DOS BOX right?
> Please be so kind and copy it here as well.
For your pleasure, attached.
> If you want us to help you, please be patient.
Hahahaha, and here I thinking I might be helping you guys! Thats the
only reason why I am still talking to ya! :-)
You and Chris are not helping anyone but disrupting the forum with
nonsense baloney.
--
HLS
Nope, nothing new here. But you did miss about 30+ years of processor
design knowledge for INTEL, MOTOROLA micros, PDx, Prime, VAX minis,
hybids, mainframes, Super computers, process controllers, simulators,
plus the 20+ more of languages and OSes, etc, etc etc, just too much to
remember.
You are EMULATING CONCURRENCY. PERIOD! True CONCURRENCY is when two
are more threads or processes are RUNNING are SAME PRECISE TIME and if
you can get that with DUAL processors without BOTTLENECKS great, but not
on a SINGLE CPU - come on, its common sense.
You might want to call it concurrency and between you, me and that
picket white fence post, I will say "ok", but only the lay person will
think you are brilliant. :-)
--
HLS
STOP TOP-POSTING. Please learn to use USENET properly.
Anyway, this is all kids stuff? Wow, your kidding right? If not, I dare you
to try telling that to the C++ Threading Standardization Group!
Tell that to Intel...
Tell that to Sun...
Tell that to Herb Sutter...
Tell that to Paul McKenney...
Tell that to your Boss!
BTWE "Pops" WHY DO YOU REFUSE TO ANSWER THE FOLLOWING QUESTION!???
>> Chris Thomasson Wrote:
>>
>> Why did you fail to check any return values?????
>>
>> ----------------------------
>>
>> Pops Replied:
>>
>> "Because you don't have to."
>> ----------------------------
>>
>>
>>
>> Chris Thomasson Wrote:
>>
>>> TCriticalSectionGrabber grab(WriterMutex);
>>> WaitForSingleObject(ReadingOk, INFINITE); if
>>> (InterlockedIncrement(&Readers) == 0) {
>>> WaitForSingleObject(ReadingActiveSemaphore, INFINITE); }
>>
>> What if WaitForSingleObject fails for whatever reason? Huh? Please
>> explain!
>>
>>
>> ----------------------------
>>
>> "Pops" Has no answer as of yet!
>> ----------------------------
>>
>>
>>
>> well, I would fire you on the spot if I was your boss! Seriously.
?????
Do tell. Your customer base wants to know the answer buddy!
BTW, I am getting ready to PLONK you...
[...]
Your code is busted on multiple fundamental levels:
modify structure under read-access
fails to check ANY return code from ANY win32 calls
Learn about how your code should not be used in ANY product whatsoever.
I hope your customers are reading this.
Oh my. You are showing your ignorance off again. What a shame...
> You are EMULATING CONCURRENCY. PERIOD! True CONCURRENCY is when two are
> more threads or processes are RUNNING are SAME PRECISE TIME and if you can
> get that with DUAL processors without BOTTLENECKS great, but not on a
> SINGLE CPU - come on, its common sense.
So you don't have to use mutual exclusion on pre-emptive multi-threading
single processor systems? Of course you do, you just don't seem to have a
clue.
[...]
Wow. Your helping the highly respected regulars who frequent this group? Oh
really?
Buy this book and READ IT:
http://www.amazon.com/Programming-POSIX-Threads-David-Butenhof/dp/0201633922
then READ IT AGAIN!!!!!!!
> You and Chris are not helping anyone but disrupting the forum with
> nonsense baloney.
Your code mutates data-structure under read-lock. You don't want to get how
absurd that action actually is. Your un-teachable indeed.
BECAUSE IT CAN FAIL DIPSHIT!
Why does WaitForSingleObject return anything BUT 'void'?
Do you think Microsoft made a mistake????????????????????
Wow. I know all about quantum's. In fact I was the first and, ONLY person
wrt USENET, that published a mechanism that solves Joe Seighs wait-free
readers/writers problem in a public forum wrt the SMR algorithm on Windows.
Find it if you can. Hire me as a consultant of you cannot. It within 1990
and 2006. Find it on google if you can. "Pops" I know you don't understand
the SMR algorithm. You think its "Kids Stuff". Your lean and do your
homework now buddy.
Anyway...
For those who have open minds and DO UNDERSTAND that mutating a shared
data=-structure protected by a READER-LOCK is ABSURD, please follow the
links and reads the following text:
You want a hind on my question. You think this is kinds stuff you moron!!!!'
Sorry for calling you a MORON...
:^)
OOPS! I forgot to publish some links... Follow links at end of following
message:
https://coolthreads.dev.java.net/servlets/ProjectForumMessageView?messageID=11001&forumID=1797
https://coolthreads.dev.java.net/servlets/ForumMessageList?forumID=1797
(read WHOLE forum... It will do you ALL some good...)
Don't flame me until you read the above, or as "Pops" puts it... "Kids
Stuff"...
:^)
No, you do not know anything about quantums. What is it? Give us a
definition. It is good to see you don't pretend to know anything about
the others I indicated above. That's good Chris. You know your place now.
> In fact I was the first and, ONLY
> person wrt USENET, that published a mechanism that solves Joe Seighs
> wait-free readers/writers problem in a public forum wrt the SMR
> algorithm on Windows.
Oh geez, you must be GOD!! You THINK you solved Joe Seigh's RW problem,
in a PUBLIC FORUM no less!! I don't know Chris, you have yet to prove
anything. I am willing to bet you solved nothing and probably made
things worst for him. In fact, lets call Joe up and ask him.
Joe, did this kid solve your problem?
--
HLS
You don't know Joe.
Actually, Joe, could... Well, I ask you as a personal favor to jump into the
sess pool....
Umm...
Could you infrom this idiot on low-overhead SMR?
Read here fool:
ahh fu%$k you...
Search sourceForge for atomic ptr plus. "pops'
Fu$%ing MoR4on<
[...]
How many systems and/or standards you have a comfortable feeling coding for?
>> Joe, did this kid solve your problem?
>
> You don't know Joe.
Oh I know Joe. Joe is that fella in your imagination! Oh Joe? Did
Christopher fix your problem with his only self-proclaimed claim to fame
RW computer statements which he never tested and still experimental?
>>> Wow. I know all about quantum's.
Come on Chris, let's see your defintion of quantums! Notice I just ask
for quantums. We already know you don't understand what interrupts are
so this is going to be interesting.
> Read here fool:
>
> ahh fu%$k you...
> Fu$%ing MoR4on<
Oh my gawd! The girl has balls!! Pretending to be a Win32 expert when
your only design project is with crayons and a coloring book, isn't
going to you past experiments stage. You need to get some more hair in
your chest to compete with me.
Later
--
HLS
Joe Seigh is in my imagination!
LOL!
I'm afraid I might further hurt your feelings more if you knew. Lets
put it this way.... I forgot more than you know but you still have time
to catch. :-)
But Chris, this is going to be the 3rd third. If you know all about
quantums, lets hear your definition of quantum. No, I am not talking
about Quantum Mechanics! Come on, atleast google it if you don't know.
The bets are on here that you will get it wrong anyway!
--
HLS
>>> You don't know Joe.
>>
>> Oh I know Joe. Joe is that fella in your imagination! Oh Joe? Did
>> Christopher fix your problem with his only self-proclaimed claim to
>> fame RW computer statements which he never tested and still experimental?
>>
>> >>> Wow. I know all about quantum's.
>>
>> Come on Chris, let's see your defintion of quantums! Notice I just ask
>> for quantums. We already know you don't understand what interrupts are
>> so this is going to be interesting.
>
> Joe Seigh is in my imagination!
>
Great! Atleast you admit it! No sweat, we all have imaginary friends to
hold up our trophies. A step in the right direction. But also notice
how you still don't know anything about quantums! Nor interrupts, nor
C/C++ contructors, initializers, nor computers, nor any kind of software
engineerng concept.
--
HLS
Joe Seigh is a real person INDEED! I trust his judgment:
I am skeptical about your poor track record to say the least! Okay. I proved
to you that Joe Seigh is in fact a real person. I will hold off on posting
my answer wrt explicit link to Windows quantum's and how they could effect
some earlier versions of Joes RCU-SMR and my vZOOM algorithm on Windows
Platform. Read, Learn, And Learn, Shut-Up Before You Think Out Loud AND
THINK, Read and Learn Some More... Then Talk...
> >>> Wow. I know all about quantum's.
>
> Come on Chris, let's see your defintion of quantums! Notice I just ask for
> quantums. We already know you don't understand what interrupts are so this
> is going to be interesting.
I know that you cannot rely on Windows being wait-free in the sense of a
RTOS scenario. Forget quantum's for a moment... Windows is not ROTS. You
simply cannot not make any guarantees wrt 40ms timeframe wrt anything you
can throw at it. Of course you can come up with a contrived bullshi% test
that proves nothing. My assertions hold true simply because Windows is NOT a
ROTS, simply because a non-deterministic scheduler, possible work-stealing,
scheduling algorithm that Windows most likely uses (e.g., it might use some
other explicitly non RTOS mechanism).
Anyway, you advised to the OP was to use code that failed to check any
return values, that Windows was somehow a RTOS if you use simplistic
non-distributed event queuing (e.g., your design was non-distributed... If
you work on multi-core you will learn about distributed message-passing
algorithms; search my name on comp.arch)!
[...]
I know I made Joe Seigh up. He IS NOT REAL!
OH SHIT YOU CAUGHT ME! I AM CRAZY FOR REALS:
http://groups.google.com/group/microsoft.public.win32.programmer.kernel/msg/95ac7ca21bb12b7c
:^P
You idiot. I know all about quantum's. Did you know that threads do not
consume 100% of there quantum's in Windows? You FOOL! You don't even know
why Windows is NOT RTOS, and why you advise wrt the OP was Bullshit! Read
this:
http://blog.kalmbachnet.de/?postid=28
I thought you would find it by now searching comp.programming.threads.
Your company needs a consultant... Just ASK!
But how can you trust him if he needed your help?
> I proved to you that Joe Seigh is in fact a real person.
He's ALIVE!!! Let me write to him and ask Joe Siegh, a person of trust,
if he was just being nice to you. You probably gave him more trouble
but seeing how you are, he was alot smarter than me and gave you a pat
on the back instead!
> I will hold off
> on posting my answer wrt explicit link to Windows quantum's
Why? Look, I just told you to look it up. Its obvious you don't know
anything the fundamentals of INTEL or WINTEL architecture. So go google
it and atleast tells us IN YOUR MIND what you think it is. Atleast this
will tell us you at the very least, you know how to do research.
> and how they
> could effect some earlier versions of Joes RCU-SMR and my vZOOM
> algorithm on Windows Platform.
I can see why you want to atleast MAKE SURE it doesn't, but you weren'
asked how quantums can screw up your code, its' probably never worked in
the first place, but thats a different issue altogether.
What is your definition of QUANTUMS!
You don't know what interrupts are, so that alone tells us that you are
not qualified to be anything close to an multi-threaded developer. But
I am not going to ask you about this fundamental hardware feature in ALL
computers, I ask you about QUANTUMS. What is it?
> My assertions hold true simply because Windows
> is NOT a ROTS,
You don't know what a RTOS is either because you never worked with one.
You clearly don't know what quantums and interrupts are and now you
think you know something about RTOS?
Trust me, get the real definition of quantums and then, maybe, maybe,
you might see the light about whether this interrupt signal can be used
for PUMP a queue.
And btw, PUMPING a QUEUE is also a terminology that is typically
understood by experienced people. So if you want to find out what that
means, critical to the OP solution, then maybe you might have a chance
my son.
--
HLS
[...]
What's you DMA Infrastructure look like on the Cell, or do you use the Sony
API's?
I've known Joe for years. He has worked at IBM an various other well
respected companies, and some important Patents have his name on them. I
have my name on some others. I dare you challenge his reputation. He would
have PLONKED my ass if I was not work talking to.
You keep responding to me, and I will be further forced to expose your
ignorance.
>
>> I will hold off on posting my answer wrt explicit link to Windows
>> quantum's
>
> Why? Look, I just told you to look it up. Its obvious you don't know
> anything the fundamentals of INTEL or WINTEL architecture. So go google
> it and atleast tells us IN YOUR MIND what you think it is. Atleast this
> will tell us you at the very least, you know how to do research.
>
>
>> and how they could effect some earlier versions of Joes RCU-SMR and my
>> vZOOM algorithm on Windows Platform.
>
> I can see why you want to atleast MAKE SURE it doesn't, but you weren'
> asked how quantums can screw up your code, its' probably never worked in
> the first place, but thats a different issue altogether.
>
> What is your definition of QUANTUMS!
Quantum is slice of allocated execution time dictated and managed by the
operating system thread and/or core scheduler. Read here moron:
http://msdn2.microsoft.com/en-us/library/aa450636.aspx
This is not rocket science. You failure to check return values is
ridiculous:
http://groups.google.com/group/comp.programming.threads/msg/a3fa49b8404e27e8
Your welcome!
>> What is your definition of QUANTUMS!
>
> Quantum is slice of allocated execution time dictated and managed by the
> operating system thread and/or core scheduler. Read here moron:
>
> http://msdn2.microsoft.com/en-us/library/aa450636.aspx
>
> This is not rocket science.
But you are not a scientist either. I see you had to resort to the CE
definition. Oh brother. Ok, you don't know. Thats a given. But atleast
you tried.
I'll give you another clue:
How is it naturally calculated?
--
HLS
Depends on the specific Platform.
[...]
How do you port you Read-Writer Bugged Class to the ARM9?
Keep in mind that the ARM9 only have interlocked swap instruction.
My vZOOM Commercial Library runs on all the ARM including, but not limited
to the ARM9
I am a computer scientist.
[...]
You know how to use Load-Linked Store-Conditional on the PPC? I, and a lot
of others do... Do tell how you port your multi-threading synchronization
scheme over to PowerPC?
Well, some academic papers prove that most know how to use LL/SC
inefficiently...
Joe Seigh, RCU (aka, Paul McKenny), and I know how to avoid it. Do you?
I think not. You response have, IMVHO, destroyed your reputation.
Tell us all how RCU interacts within the Linux Kernel on at least two
different platforms?
Ahh shit!
I cannot forget:
Dmitriy Vyukov
>
> I think not. You response have, IMVHO, destroyed your reputation.
Post something innovative on comp.programming.threads to try and repair the
pile of rubble previous referred to as your reputation on USENET.
For extra credit... Make the Alpha on of the Platforms you decide to use in
your answer "Pops"!
Actually forget that...
You would end up cast your pearls before a certain piece of swine.
You need to check you return values to compete with me.
This is platform dependant... BTW, what's wrong with Windows CE way of doing
it?
Ok, I'm bored now. This weekend escapade was nice, thanks for the amusement.
--
HLS
Stop-Top Posting!
Anyway, what are you talking about?
My god. You take read access and take write access to write to a
data-structure!?
Why not do:
BOOL Get(TWCFWatchEvent &o) {
TWriterGrabber grab(Mutex);
if (IsEmpty()) return FALSE;
o = RemoveTail();
return TRUE;
}
???????????
Now, children. Chill. You're descending into personal insults. If this
were a moderated discussion forum you'd both have been shut off by now;
so please think about what you're saying and attempt to act with a
little professional decorum.
Chris, I know you're capable of a much better discussion style. We're
not dealing with SenderX, remember? Don't let "Pops" get your goat...
it's hard enough to find goats around here. (I kinda wonder where Joe
is, because I have a feeling he might enjoy this sort of snark hunt. Oh
well.)
I don't know anything about "Pops" beyond this morass, but at this point
you're acting a lot like a troll with no relevant or meaningful
background. I suspect it was Chris who found your original post and
copied it over here, since the first post I saw was a response from him.
I suppose I can see what he thought to accomplish by directing the
discussion into a forum focussed on concurrency. Equally clearly, the
attempt was a failure. Take the discussion back where it started,
please, or argue at each other via private email.
This argument adds nothing to the newsgroup, and even the mild amusement
value is long since worn thin.
I was going to stay out of this one. :)
If I do get in a discussion that gets out of hand I tend to just bail
on them as they're counter productive at that point and and waste of
time.
c.p.t. has been kind of quiet lately. Writers strike?
--
Joe Seigh
When you get lemons, you make lemonade.
When you get hardware, you make software.
> c.p.t. has been kind of quiet lately. Writers strike?
You mean, as in a secret cabal of conspirators hiring professional hack
writers to invent a series of colorful but quirky pseudo-computer-geek
characters and develop varied plot lines of plausible but unlikely
techno-babble arguments for the amusement of the conspirators?
Nah.
Then again... it could explain a lot. ;-)
He got me big time. I was not able to get my point across to him. I am
giving up on this thread.
> it's hard enough to find goats around here. (I kinda wonder where Joe is,
> because I have a feeling he might enjoy this sort of snark hunt. Oh well.)
>
> I don't know anything about "Pops" beyond this morass, but at this point
> you're acting a lot like a troll with no relevant or meaningful
> background. I suspect it was Chris who found your original post and copied
> it over here, since the first post I saw was a response from him. I
> suppose I can see what he thought to accomplish by directing the
> discussion into a forum focussed on concurrency. Equally clearly, the
> attempt was a failure. Take the discussion back where it started, please,
> or argue at each other via private email.
I have failed indeed.
Yup. I think I royally screwed up on this one. I have to hand it to "Pops"
in that he was 100% successful in temporarily resurrecting SenderX.
;^(...
> c.p.t. has been kind of quiet lately. Writers strike?
lol :^)
Hmmm.
CT> Wow. I know all about quantum's.
P> No, you do not know anything about quantums. What is it? [...]
Both of you would look less foolish to the rest of us if you spelled
"quanta" properly and used a plural pronoun when there is a plural
antecedent.
Who is "US?" Is this a "CLUB" you belong to?
Foolish are the ones who need a reason for living by jumping into a long
dead thread with anal retentive, ad nausem, multi-forum cross posting,
bandwidth wasting, absolute meaningless comments which can only possibly
serve one purpose - a bored vain attempt to make you feel smarter and
part of something. Whatever the reasons, I don't give a damn if it works
for you or not, or its makes you better member of your CLUB!!
B4I4QRU/18
> J de Boyne Pollard wrote:
>>
>> P> No, you do not know anything about quantums. What is it?
>> [...]
>>
>> Both of you would look less foolish to the rest of us if you
>> spelled "quanta" properly and used a plural pronoun when there
>> is a plural antecedent.
>
> Who is "US?" Is this a "CLUB" you belong to?
>
> Foolish are the ones who need a reason for living by jumping
> into a long dead thread with anal retentive, ad nausem,
You dropped a letter from "ad nauseam", along with a couple of
hyphens.
(Posted from the cross-posted AUE; it's what we do....)
--
Cheers, Harvey
CanEng and BrEng, indiscriminately mixed