[Mono-dev] asynchronous exceptions

Jonathan Pryor jonpryor at vt.edu
Wed Jun 18 10:34:05 EDT 2008


On Wed, 2008-06-18 at 12:22 +0200, Bastian Schmitz wrote:
> I am planning to have a language element, which ensures that a given condition 
> stays fulfilled during the execution of block of code. If the condition is 
> violated an exception should be risen. The condition is (probably) going to 
> be checked/evaluated by another thread, who should inform the first one in 
> case of violation of the condition.

Would you need the condition to be true throughout the block of code,
or just at the beginning and end of the block of code?

If you just need the beginning and end of the block, there's already a
language construct that you can use (meaning you wouldn't need to extend
the language or runtime in any way): the `using' block, which ensures
that a method (Dispose()) is executed at the end of the specified block:

	using (var f = new FileStream (...)) {
	}
	// f.Dispose() implicitly called here, which for FileStream
	// will close the file.

So if you only need start/end support, you would only need to create a
new class which would perform the check in the constructor and Dispose()
method:

	struct AssertInvariant : IDisposable {
		Func<bool> checker;

		public AssertInvariant (Func<bool> checker)
		{
			this.checker = checker;
			Assert ();
		}

		void Assert ()
		{
			if (!checker())
				Thread.CurrentThread.Abort ();
		}

		public void Dispose ()
		{
			Assert ();
		}
	}

Use:

	int x = 0, y = 1;
	using (new AssertInvariant (() => x >= 0, y == 1)) {
		// manipulate x & y
	}
	// AssertInvariant.Assert() invoked here.

If a simple begin/end check is in appropriate, and you need it asserted
throughout the block (which would make it difficult to break any
invariants for short periods of time, as may be needed to transfer from
one valid state to another), _then_ you would need a new language
construct + compiler change.  I would be dubious of such a feature,
though.

Even Eiffel, patron saint of Design By Contract-goodness, disables
invariants within the method body, and only checks at method enter and
exit (of public methods).

> This pattern resembles to the asynchronous exception used by the 
> Thread.Abort() method being triggered by an external thread, catching the 
> ThreadAbortException and canceling the abort afterwards.
> I am wondering if there is a safe way to achieve this functionality with the 
> crl/mono runtime.

That's another problem -- the ThreadAbortException() can only be
canceled (via Thread.ResetAbort()) if Thread.Abort() was called by the
current thread, NOT by another thread.  So if Thread1 aborts Thread2,
then Thread2 cannot abort the Abort.

If you need Thread.ResetAbort() behavior, you need to have
Thread.Abort() called on the aborting thread, as AssertInvariant above
does.

 - Jon




More information about the Mono-devel-list mailing list