 |
|
 |
I got the follwing errors when I compile the demp-app:
Kompilierung läuft...
CriticalSection.cpp
d:\entwicklung\cpp\_cpp_samples\_threads\advanced critical section\advanced_criticalsection_demo\criticalsection.h(28) : error C2664: 'InterlockedCompareExchange' : Konvertierung des Parameters 1 von 'long *' in 'void ** ' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
d:\entwicklung\cpp\_cpp_samples\_threads\advanced critical section\advanced_criticalsection_demo\criticalsection.h(52) : error C2664: 'InterlockedCompareExchange' : Konvertierung des Parameters 1 von 'long *' in 'void ** ' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
CriticalSectionTest.cpp
d:\entwicklung\cpp\_cpp_samples\_threads\advanced critical section\advanced_criticalsection_demo\criticalsection.h(28) : error C2664: 'InterlockedCompareExchange' : Konvertierung des Parameters 1 von 'long *' in 'void ** ' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
d:\entwicklung\cpp\_cpp_samples\_threads\advanced critical section\advanced_criticalsection_demo\criticalsection.h(52) : error C2664: 'InterlockedCompareExchange' : Konvertierung des Parameters 1 von 'long *' in 'void ** ' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
TestObject.cpp
d:\entwicklung\cpp\_cpp_samples\_threads\advanced critical section\advanced_criticalsection_demo\criticalsection.h(28) : error C2664: 'InterlockedCompareExchange' : Konvertierung des Parameters 1 von 'long *' in 'void ** ' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
d:\entwicklung\cpp\_cpp_samples\_threads\advanced critical section\advanced_criticalsection_demo\criticalsection.h(52) : error C2664: 'InterlockedCompareExchange' : Konvertierung des Parameters 1 von 'long *' in 'void ** ' nicht moeglich
Die Typen, auf die verwiesen wird, sind nicht verwandt; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
Generieren von Code...
Fehler beim Ausführen von cl.exe.
CriticalSectionTest.exe - 6 Fehler, 0 Warnung(en)
But why ? ?
Hope you can help me !!!
Martin
|
|
|
|
 |
|
|
 |
|
 |
Auch, habe jedoch dieses Demo - Projekt mit VS 6 getestet.
|
|
|
|
 |
|
 |
You are setting m_dwThreadId to zero after you have released the lock. Thus, this could happen:
Thread#1 Unlock: DoExchange
Thread#2 Lock: DoExchange
Thread#2 Lock: Set m_dwTreadId = Get...
Thread#1 Unlock: Set m_dwThreadId = 0
And that compare/exchange routine doesn't exist on 95.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
 |
|
 |
More importantly the critocal section here would fail if there are more than 1 thread swaiting for a resource. All the threads waiting will be released. The author is repeating the same mistake which he did when he posted the article some time back. I hope anyone wishing to use it are careful enough to understand that this ain't a good alternative to critical section
|
|
|
|
 |
|
 |
He is using a auto-reset event so PulseEvent will only release one thread. He also calls Lock after release to retry the lock. So unless I missed the boat (still have vacation brain on), even if all threads were released, it would just be a race to see who got the lock first.
But as William pointed out, the way he is using PulseEvent leaves a window of failure open.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
 |
|
 |
There's other problems as well. The PulseEvent causes a race that can result in deadlock. Using an auto-reset event and SetEvent instead will leave a race condition, but I *think* it will be a race that simply won't cause failure (should be equivalent to a "spurious wakeup").
The recursive call to Lock is also broken. You pass in the same dwTimeOut, which could (theoretically) cause an infinite wait due to race conditions, and at the very least is likely to cause lock attempts that take longer then the specified timeout.
Note also that the compare/exchange routine doesn't exist on 95 for a reason. 95 supports processors that don't have a compare/exchange operation. If you try and implement your own compare/exchange in assembly you can't claim support for 95 but only support for 95 on certain processors.
Others have pointed you to the metered section stuff, but something closer to what you're doing can be found in the optex example. This used to be in MSDN, but I can't locate it now. In any event, you can still find it on the web at http://www.microsoft.com/msj/0198/win32textfigs.htm. The goals were different, but the COptex class provides a TryEnter method that's very similar.
William E. Kempf
|
|
|
|
 |
|
 |
Ack, I didn't even noticed the PulseEvent. I bet that one call is the source of TONs of event problems. I avoid that damn thing like the plague.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
 |
|
 |
You are correct about SetEvent fixing the problem but leaving you with a "spurious wakeup". Which of course is better than a deadlock.
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
 |
|
 |
Yes but set event on AutoResetEvent only puts one thread in the ready queue, so I don't see the spurious wakeup problem?
|
|
|
|
 |
|
 |
"The recursive call to Lock is also broken. You pass in the same dwTimeOut, which could (theoretically) cause an infinite wait due to race conditions, and at the very least is likely to cause lock attempts that take longer then the specified timeout."
I don't see that in the current code (maybe past version.) Only one thread is pulsed and that thread checks lock with 0 timeout, so not race I can see.
|
|
|
|
 |
|
 |
Bug reported by Dalle is fixed...
|
|
|
|
 |
|
 |
I'm sorry to say this but the implementation is not thread safe in itself. Lock() could return true for more than one thread at a time. Use "if (InterlockedCompareExchange(...) == ...)" instead of "if (m_lLockCount)". The same thing applies for Unlock, it does not always pulse the event.
|
|
|
|
 |
|
 |
Good suggestion. I'll do it...
|
|
|
|
 |
|
|
 |
|
 |
Tried to compile the msdn metered section sample and got the following error: \Metered.cpp(274): error C2664: 'InterlockedExchange' : cannot convert parameter 1 from 'BOOL *' to 'volatile LONG *'
Any idea of how to fix it? THis would be great to use if it would only work.
|
|
|
|
 |
|
 |
You probably need to install the latest Platform SDK.
/Mikael
|
|
|
|
 |
|
 |
As sizeof(BOOL) == sizeof(LONG) you should be able to explicit cast the BOOL* to LONG*.
InterlockedExchange((LONG*) &(lpMetSect->lpSharedInfo->fInitialized), TRUE);
Or you could change
BOOL fInitialized;
to
LONG fInitialized;
|
|
|
|
 |
|
|
 |
|
 |
It is not needed as a LONG* will implicitly be cast to a volatile LONG*. The same way as a LONG* will implicitly be cast to a const LONG*.
|
|
|
|
 |
|
 |
I just copied the code from the msdn page. Trying to get an example that works. Using the latest sdk's. Can someone possibly post a fix or a version that works? Thanks
|
|
|
|
 |
|
|
 |
|
 |
Thanks. It compiles great now under vc7 and .net.
|
|
|
|
 |