[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: [DotGNU]Additional Monitors test cases
From: |
Russell Stuart |
Subject: |
RE: [DotGNU]Additional Monitors test cases |
Date: |
05 May 2004 15:35:17 +1000 |
On Wed, 2004-05-05 at 14:26, Thong (Tum) Nguyen wrote:
> I haven't had a chance to run your tests but the last two look highly time
> dependent. For example:
>
> public String testMonitorAbortAfterWait()
> {
> ...
> lock (this.o)
> {
> Monitor.Pulse(o);
> Thread.Sleep(2*1000);
> thread.Abort();
> this.seen = true;
> }
> ...
> }
>
> void threadFunc()
> {
> Monitor.Enter(this.o);
> lock (this)
> {
> Monitor.Pulse(this);
> }
> try
> {
> Monitor.Wait(this.o);
> this.result = "Expected
> System.Threading.ThreadAbortExcep
> return;
> }
> catch (ThreadAbortException)
> {
> ...
> }
>
> The first thread pulses "o" which causes the thread inside threadFunc to
> wakeup. Once it wakes up, it immediately returns with "Expected
> ThreadAbortException". The first thread doesn't even get a chance to abort
> the thread.
Ahh, I see where the problem lies. This is not documented at all well
by Microsoft. Fortunately, the C# Monitors are meant to be a fairly
exact emulation of the java monitors, and thus you can rely on the Java
doco for this case. That is why I sent you a java URL - so you could
read and understand what I was on about. Here is the URL again:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#wait(long)
You may not be convinced that C# monitors are meant to be an exact
emulation of the Java ones. I offer three arguments re why I think they
are:
1. It would be very yucky if they behaved in any other manner. When
programmer writes:
lock (obj) { ... @1 ...; wait(obj); ... @2 ... }
He justifiably expects the code at both @1 and @2 to be guarded
by the lock. If that were no so, every Java / C# book in existence
would say the above is bad style. They would instead say that since
there are no firm guarantees that the lock is in place when @2 is
executed, you should instead write this:
lock (obj) { ... @1 ...; wait(obj); } ... @2 ...
2. I have a book titled "C# for the Java programmer", ISBN 0735617791.
It says that are the same.
3. Look at this URL.
http://www.di.unipi.it/~boerger/Papers/CSharp/CsharpThread.pdf
It is a excellent reference on C# threads. I read with some
amusement in the introduction:
"A program developer has to rely solely on the class library
documentation that comes with Microsoft s .NET framework Software
Development Kit [11]. Unfortunately, that documentation is not
very precise with respect to threads, locks and memory issues.
... For example, specifications of Thread.Interrupt,
Thread.Suspend and Thread.Resume are not included in [5]."
:
[5] Common Language Infrastructure (CLI). Standard ECMA 335, 2001.
Oh joy .. that does make life hard, doesn't it. Anyway, near the
top of page 17 this comment appears:
"Injecting a ThreadAbortException or a ThreadInterruptedException
into a thread means to create a new excpetion object and to force
the thread to throw the exception (using Fail). If the thread is
Syncing, Sleeping or Joined, its execution state is changed to
Active in order that the exception can propagate upwards and
probably terminate the thread. If the thread is Waiting, it is
moved to the readyQueue and has to re-acquire the lock, since in
this case the thread is still in a critical section of code and
possible exception handlers and finally blocks should only be
executed under the exclusive control of the monitor. If the thread
is Pulsed, its execution state is not updated, since the thread
has to re-acquire the lock before propagating the exception."
You could do a lot worse than use this document as the spec for
the PNet C# thread code.
Have I convinced you?
PS, I posted this to the developers list, as I think this discussion is
important.