[Mono-devel-list] [PATCH] Reworked unified Locale classes

Jonathan Pryor jonpryor at vt.edu
Thu Jun 23 08:15:21 EDT 2005


On Thu, 2005-06-23 at 11:18 +0200, Kornél Pál wrote:
> private static ResourceManager GetResourceManager ()
> {
>  if (resources == null)
>   lock (resourcesLock) {
>    if (resources == null)
>     resources = new GetTextResourceManager (typeof (Locale).Assembly.GetName
> ().Name, typeof (Locale).Assembly);
>   }
>  return resources;
> }
> 
> I think this is good, because it is intended to initialize resources only
> once.

It looks good.  It acts good.  It isn't good.

See:
	http://galactus.ximian.com/pipermail/mono-devel-list/2004-February/004101.html
	http://blogs.msdn.com/cbrumme/archive/2003/05/17/51445.aspx

In short, it will work correctly....on x86.  *Maybe* on other
processors.  But it won't work *everywhere*.  The problem is that the
memory model that the CLI defines has looser semantics than x86
provides, so you can't actually hit the race condition on x86, but it
will exist on Itanium (I think).

Where's the race?  It's between the processor, cache, and main memory on
a multi-CPU machine.  Dragons be there; be afraid. :-)

There are four solutions:

	- Make `resources' `volatile', which disables any caching the 
	  processor might do.  This effectively makes reads & writes
	  a memory barrier operation, slowing things down

	- Always acquire a lock before reading `resources' -- also 
	  slow, due to the locking required.

	- If it's safe to create multiple instances of 
	  GetTextResourceManager, you could use an 
	  Interlocked.CompareExchange to set `resource' for lock-free
	  thread-safe code.  See:

	  http://mono.myrealbox.com/source/trunk/mcs/class/System/System.Diagnostics/TraceImpl.cs

	  And search for `#if !NO_LOCK_FREE' for an example.

	- Place `resource' into a different class and use a static 
	  constructor.  GetResourceManager can then catch for the 
	  TypeInitializationException and provide fallback behavior.

Personally, I'd go for the static constructor, as it's easier to get
right.  I think the Interlocked.CompareExchange code is correct (I wrote
it), but I'm no lock-free expert, so there may be issues with it (but I
did sleep at a Holiday Inn last night. :-)

 - Jon





More information about the Mono-devel-list mailing list