Mercurial > projects > ldc
diff tango/example/synchronization/mutex.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/example/synchronization/mutex.d Fri Jan 11 17:57:40 2008 +0100 @@ -0,0 +1,248 @@ +/******************************************************************************* + copyright: Copyright (c) 2006 Juan Jose Comellas. All rights reserved + license: BSD style: $(LICENSE) + author: Juan Jose Comellas <juanjo@comellas.com.ar> + Converted to use core.sync by Sean Kelly <sean@f4.ca> +*******************************************************************************/ + +private import tango.core.sync.Mutex; +private import tango.core.Exception; +private import tango.core.Thread; +private import tango.io.Stdout; +private import tango.text.convert.Integer; +debug (mutex) +{ + private import tango.util.log.Log; + private import tango.util.log.ConsoleAppender; + private import tango.util.log.DateLayout; +} + + +/** + * Example program for the tango.core.sync.Mutex module. + */ +void main(char[][] args) +{ + debug (mutex) + { + Logger log = Log.getLogger("mutex"); + + log.addAppender(new ConsoleAppender(new DateLayout())); + + log.info("Mutex test"); + } + + testNonRecursive(); + testLocking(); + testRecursive(); +} + +/** + * Test that non-recursive mutexes actually do what they're supposed to do. + * + * Remarks: + * Windows only supports recursive mutexes. + */ +void testNonRecursive() +{ + version (Posix) + { + debug (mutex) + { + Logger log = Log.getLogger("mutex.non-recursive"); + } + + Mutex mutex = new Mutex(Mutex.Type.NonRecursive); + bool couldLock; + + try + { + mutex.lock(); + debug (mutex) + log.trace("Acquired mutex"); + couldLock = mutex.tryLock(); + if (couldLock) + { + debug (mutex) + { + log.trace("Re-acquired mutex"); + log.trace("Releasing mutex"); + } + mutex.unlock(); + } + else + { + debug (mutex) + log.trace("Re-acquiring the mutex failed"); + } + debug (mutex) + log.trace("Releasing mutex"); + mutex.unlock(); + } + catch (SyncException e) + { + Stderr.formatln("Sync exception caught when testing non-recursive mutexes:\n{0}\n", e.toString()); + } + catch (Exception e) + { + Stderr.formatln("Unexpected exception caught when testing non-recursive mutexes:\n{0}\n", e.toString()); + } + + if (!couldLock) + { + debug (mutex) + log.info("The non-recursive Mutex test was successful"); + } + else + { + debug (mutex) + { + log.error("Non-recursive mutexes are not working: " + "Mutex.tryAcquire() did not fail on an already acquired mutex"); + assert(false); + } + else + { + assert(false, "Non-recursive mutexes are not working: " + "Mutex.tryAcquire() did not fail on an already acquired mutex"); + } + } + } +} + +/** + * Create several threads that acquire and release a mutex several times. + */ +void testLocking() +{ + const uint MaxThreadCount = 10; + const uint LoopsPerThread = 1000; + + debug (mutex) + { + Logger log = Log.getLogger("mutex.locking"); + } + + Mutex mutex = new Mutex(); + uint lockCount = 0; + + void mutexLockingThread() + { + try + { + for (uint i; i < LoopsPerThread; i++) + { + synchronized (mutex) + { + lockCount++; + } + } + } + catch (SyncException e) + { + Stderr.formatln("Sync exception caught inside mutex testing thread:\n{0}\n", e.toString()); + } + catch (Exception e) + { + Stderr.formatln("Unexpected exception caught inside mutex testing thread:\n{0}\n", e.toString()); + } + } + + ThreadGroup group = new ThreadGroup(); + Thread thread; + char[10] tmp; + + for (uint i = 0; i < MaxThreadCount; i++) + { + thread = new Thread(&mutexLockingThread); + thread.name = "thread-" ~ format(tmp, i); + + debug (mutex) + log.trace("Created thread " ~ thread.name); + thread.start(); + + group.add(thread); + } + + debug (mutex) + log.trace("Waiting for threads to finish"); + group.joinAll(); + + if (lockCount == MaxThreadCount * LoopsPerThread) + { + debug (mutex) + log.info("The Mutex locking test was successful"); + } + else + { + debug (mutex) + { + log.error("Mutex locking is not working properly: " + "the number of times the mutex was acquired is incorrect"); + assert(false); + } + else + { + assert(false,"Mutex locking is not working properly: " + "the number of times the mutex was acquired is incorrect"); + } + } +} + +/** + * Test that recursive mutexes actually do what they're supposed to do. + */ +void testRecursive() +{ + const uint LoopsPerThread = 1000; + + debug (mutex) + { + Logger log = Log.getLogger("mutex.recursive"); + } + + Mutex mutex = new Mutex; + uint lockCount = 0; + + try + { + for (uint i = 0; i < LoopsPerThread; i++) + { + mutex.lock(); + lockCount++; + } + } + catch (SyncException e) + { + Stderr.formatln("Sync exception caught in recursive mutex test:\n{0}\n", e.toString()); + } + catch (Exception e) + { + Stderr.formatln("Unexpected exception caught in recursive mutex test:\n{0}\n", e.toString()); + } + + for (uint i = 0; i < lockCount; i++) + { + mutex.unlock(); + } + + if (lockCount == LoopsPerThread) + { + debug (mutex) + log.info("The recursive Mutex test was successful"); + } + else + { + debug (mutex) + { + log.error("Recursive mutexes are not working: " + "the number of times the mutex was acquired is incorrect"); + assert(false); + } + else + { + assert(false, "Recursive mutexes are not working: " + "the number of times the mutex was acquired is incorrect"); + } + } +}