Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Changeset 2010

Show
Ignore:
Timestamp:
04/09/07 20:12:58 (2 years ago)
Author:
jcomellas
Message:

* Changed tango.util.locks.Condition interface to make it compatible with the

integrated locks proposal.

* Cleaned up comments for the modules in the tango.util.locks package.
* Removed unnecessary modules from the integrated locks proposal.
* Fixed ticket #363.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/example/locks/condition.d

    r1901 r2010  
    66 
    77private import tango.util.locks.Condition; 
    8 private import tango.util.locks.Barrier; 
    98private import tango.util.locks.LockException; 
    109private import tango.core.Thread; 
     
    3635 
    3736/** 
    38  * Test for Condition.notifyOne(). 
     37 * Test for Condition.notify(). 
    3938 */ 
    4039void testNotifyOne() 
     
    4645 
    4746    scope Mutex     mutex   = new Mutex(); 
    48     scope Condition cond    = new Condition(); 
     47    scope Condition cond    = new Condition(mutex); 
    4948    int             waiting = 0; 
    5049    Thread          thread; 
     
    6564                log.trace("Acquired mutex"); 
    6665 
     66            scope(exit) 
     67            { 
     68                debug (condition) 
     69                    log.trace("Releasing mutex"); 
     70                mutex.release(); 
     71            } 
     72 
    6773            waiting++; 
    6874 
     
    7177                debug (condition) 
    7278                    log.trace("Waiting on condition variable"); 
    73                 cond.wait(mutex); 
     79                cond.wait(); 
    7480            } 
    7581 
    7682            debug (condition) 
    7783                log.trace("Condition variable was signaled"); 
    78  
    79             debug (condition) 
    80                 log.trace("Releasing mutex"); 
    81             mutex.release(); 
    8284        } 
    8385        catch (LockException e) 
     
    129131        debug (condition) 
    130132            log.trace("Notifying test thread"); 
    131         cond.notifyOne(); 
     133        cond.notify(); 
    132134 
    133135        debug (condition) 
     
    175177 
    176178    scope Mutex     mutex   = new Mutex(); 
    177     scope Condition cond    = new Condition(); 
     179    scope Condition cond    = new Condition(mutex); 
    178180    int             waiting = 0; 
    179181 
     
    202204                debug (condition) 
    203205                    log.trace("Waiting on condition variable"); 
    204                 cond.wait(mutex); 
     206                cond.wait(); 
    205207            } 
    206208 
  • trunk/example/locks/readwritemutex.d

    r1901 r2010  
    3030    debug (readwritemutex) 
    3131    { 
    32         scope Logger log = Log.getLogger("rwmutex"); 
     32        scope Logger log = Log.getLogger("readwritemutex"); 
    3333 
    3434        log.addAppender(new ConsoleAppender(new DateLayout())); 
     
    4747        debug (readwritemutex) 
    4848        { 
    49             Logger log = Log.getLogger("rwmutex." ~ Thread.getThis().name()); 
     49            Logger log = Log.getLogger("readwritemutex." ~ Thread.getThis().name()); 
    5050 
    5151            log.trace("Starting reader thread"); 
     
    7373        debug (readwritemutex) 
    7474        { 
    75             Logger log = Log.getLogger("rwmutex." ~ Thread.getThis().name()); 
     75            Logger log = Log.getLogger("readwritemutex." ~ Thread.getThis().name()); 
    7676 
    7777            log.trace("Starting writer thread"); 
  • trunk/example/locks/semaphore.d

    r1901 r2010  
    44  author:      Juan Jose Comellas <juanjo@comellas.com.ar> 
    55*******************************************************************************/ 
     6 
     7module semaphore; 
    68 
    79private import tango.util.locks.Semaphore; 
  • trunk/patches/proposals/integrated_locks/tango/util/locks/Mutex.d

    r1901 r2010  
    2828 
    2929    /** 
    30      * Mutex wrapper that maps to a <CRITICAL_SECTION> on Windows and to a 
    31      * <pthread_mutex_t> on UNIX. This implementation is optimized for locking 
    32      * threads that are in the same process. 
     30     * Mutex wrapper that's only valid for threads in the same process. 
     31     * This implementation is optimized for locking threads that are in the 
     32     * same process. It maps to a $(D_CODE CRITICAL_SECTION) on Windows and to 
     33     * a $(D_CODE pthread_mutex_t) on UNIX. Mutexes on Windows are always 
     34     * recursive, even if the $(D_CODE NonRecursive) mutex type is used. 
    3335     */ 
    3436    public class Mutex 
     
    3739         * Accessor for the underlying mutex implementation. 
    3840         */ 
    39         package pthread_mutex_t* mutex() 
     41        package override pthread_mutex_t* mutex() 
    4042        { 
    4143            // DMD's intrinsic function gives us access to the Object's mutex  
     
    8385 
    8486        /** 
    85          * Check the 'errorCode' argument against possible errno values and 
    86          * throw an exception with the description of the error. 
     87         * Check the $(D_PARAM errorCode) argument against possible values 
     88         * of $(D_CODE SysError.lastCode()) and throw an exception with the 
     89         * description of the error. 
    8790         * 
    8891         * Params: 
    89          * errorCode    = errno value; must not be 0. 
     92         * errorCode    = SysError.lastCode() value; must not be 0. 
    9093         * file         = name of the source file where the check is being 
    9194         *                made; you would normally use __FILE__ for this 
     
    97100         * Throws: 
    98101         * AlreadyLockedException when the mutex has already been locked by 
    99          * another thread (EBUSY); DeadlockException when the mutex has already 
    100          * been locked by the calling thread (EDEADLK); InvalidMutexException 
    101          * when the mutex has not been properly initialized (EINVAL); 
    102          * MutexOwnerException when the calling thread does not own the mutex 
    103          * (EPERM); LockException for any of the other cases in which errno is 
    104          * not 0. 
    105          */ 
    106         protected final void checkError(int errorCode, char[] file, uint line) 
     102         * another thread; DeadlockException when the mutex has already 
     103         * been locked by the calling thread; InvalidMutexException when the 
     104         * mutex has not been properly initialized; MutexOwnerException when 
     105         * the calling thread does not own the mutex; LockException for any 
     106         * of the other cases in which $(D_PARAM errorCode) is not 0. 
     107         */ 
     108        protected final void checkError(uint errorCode, char[] file, uint line) 
    107109        in 
    108110        { 
     
    229231     * Mutex wrapper that's only valid for threads in the same process. 
    230232     * This implementation is optimized for locking threads that are in the 
    231      * same process. It maps to a <CRITICAL_SECTION> on Windows and to a 
    232      * <pthread_mutex_t> on UNIX. Mutexes on Windows are always recursive, 
    233      * even if the <NonRecursive> mutex type is used. 
     233     * same process. It maps to a $(D_CODE CRITICAL_SECTION) on Windows and to 
     234     * a $(D_CODE pthread_mutex_t) on UNIX. Mutexes on Windows are always 
     235     * recursive, even if the $(D_CODE NonRecursive) mutex type is used. 
    234236     */ 
    235237    public class Mutex 
     
    279281 
    280282        /** 
    281          * 
     283         * Initialize the mutex. 
    282284         */ 
    283285        public this() 
     
    286288            if (_mutex == cast(HANDLE) NULL) 
    287289            { 
    288                 checkError(GetLastError(), __FILE__, __LINE__); 
     290                checkError(SysError.lastCode(), __FILE__, __LINE__); 
    289291            } 
    290292        } 
     
    307309            if (result != WAIT_OBJECT_0) 
    308310            { 
    309                 checkError(GetLastError(), __FILE__, __LINE__); 
     311                checkError(SysError.lastCode(), __FILE__, __LINE__); 
    310312            } 
    311313        } 
     
    344346            else 
    345347            { 
    346                 checkError(GetLastError(), __FILE__, __LINE__); 
     348                checkError(SysError.lastCode(), __FILE__, __LINE__); 
    347349                return false; 
    348350            } 
     
    356358            if (ReleaseMutex(_mutex) != 0) 
    357359            { 
    358                 checkError(GetLastError(), __FILE__, __LINE__); 
    359             } 
    360         } 
    361  
    362         /** 
    363          * Check the result from the GetLastError() Windows function and 
    364          * throw an exception with the description of the error. 
     360                checkError(SysError.lastCode(), __FILE__, __LINE__); 
     361            } 
     362        } 
     363 
     364        /** 
     365         * Check the $(D_PARAM errorCode) argument against possible values 
     366         * of $(D_CODE SysError.lastCode()) and throw an exception with the 
     367         * description of the error. 
    365368         * 
    366369         * Params: 
    367          * file     = name of the source file where the check is being made; you 
    368          *            would normally use __FILE__ for this parameter. 
    369          * line     = line number of the source file where this method was called; 
    370          *            you would normally use __LINE__ for this parameter. 
     370         * errorCode    = SysError.lastCode() value; must not be 0. 
     371         * file         = name of the source file where the check is being 
     372         *                made; you would normally use __FILE__ for this 
     373         *                parameter. 
     374         * line         = line number of the source file where this method 
     375         *                was called; you would normally use __LINE__ for 
     376         *                this parameter. 
    371377         * 
    372378         * Throws: 
    373379         * AccessDeniedException when the caller does not have permissions to 
    374380         * use the mutex; LockException for any of the other cases in which 
    375          * GetLastError() is not 0. 
    376          */ 
    377         protected void checkError(DWORD errorCode, char[] file, uint line) 
     381         * $(D_PARAM errorCode) is not 0. 
     382         */ 
     383        protected void checkError(uint errorCode, char[] file, uint line) 
    378384        in 
    379385        { 
    380             assert(errorCode != 0); 
     386            char[10] tmp; 
     387 
     388            assert(errorCode != 0, "checkError() was called with SysError.lastCode() == 0 on file " ~ 
     389                                   file ~ ":" ~ format(tmp, line)); 
    381390        } 
    382391        body 
  • trunk/tango/util/locks/Barrier.d

    r1901 r2010  
    2020     * Implements "barrier synchronization". 
    2121     * 
    22      * This class allows <count> number of threads to synchronize their 
    23      * completion of (one round of) a task, which is known as "barrier 
    24      * synchronization". After all the threads call <wait()> on the barrier 
    25      * they are all atomically released and can begin a new round. 
     22     * This class allows $(D_PARAM count) number of threads to synchronize 
     23     * their completion of (one round of) a task, which is known as "barrier 
     24     * synchronization". After all the threads call $(D_CODE wait()) on the  
     25     * barrier they are all atomically released and can begin a new round. 
    2626     */ 
    2727    public class Barrier 
     
    3030 
    3131        /** 
    32          * Initialize the barrier to synchronize <count> threads. 
     32         * Initialize the barrier to synchronize $(D_PARAM count) threads. 
    3333         */ 
    3434        public this(uint count) 
     
    6161 
    6262        /** 
    63          * Block the caller until all <count> threads have called 
    64          * Barrier.wait() and then allow all the caller threads to continue 
    65          * in parallel. 
     63         * Block the caller until all $(D_PARAM count) threads have called 
     64         * $(D_CODE Barrier.wait()) and then allow all the caller threads to  
     65         * continue in parallel. 
    6666         */ 
    6767        public void wait() 
     
    7676 
    7777        /** 
    78          * Check the 'errorCode' argument against possible errno values and 
    79          * throw an exception with the description of the error. 
     78         * Check the $(D_PARAM errorCode) argument against possible values 
     79         * of $(D_CODE SysError.lastCode()) and throw an exception with the 
     80         * description of the error. 
    8081         * 
    8182         * Params: 
    82          * errorCode    = errno value; must not be 0. 
     83         * errorCode    = SysError.lastCode() value; must not be 0. 
    8384         * file         = name of the source file where the check is being 
    8485         *                made; you would normally use __FILE__ for this 
     
    9091         * Throws: 
    9192         * AlreadyLockedException when the barrier cannot be destroyed because 
    92          * it is already locked by another thread (EBUSY); 
    93          * InvalidBarrierException when the barrier has not been properly 
    94          * initialized (EINVAL); LockException for any of the other cases in 
    95          * which errno is not 0. 
    96          */ 
    97         protected void checkError(int errorCode, char[] file, uint line) 
     93         * it is already locked by another thread; InvalidBarrierException 
     94         * when the barrier has not been properly initialized; LockException 
     95         * for any of the other cases in which $(D_PARAM errorCode) is not 0. 
     96         */ 
     97        protected void checkError(uint errorCode, char[] file, uint line) 
    9898        in 
    9999        { 
     
    127127    /** 
    128128     * Implements "barrier synchronization". 
    129      * This class allows <count> number of threads to synchronize their 
    130      * completion of (one round of) a task, which is known as "barrier 
    131      * synchronization". After all the threads call <wait()> on the barrier 
    132      * they are all atomically released and can begin a new round. 
     129     * This class allows $(D_PARAM count) number of threads to synchronize 
     130     * their completion of (one round of) a task, which is known as "barrier 
     131     * synchronization". After all the threads call $(D_CODE wait()) on the 
     132     * barrier they are all atomically released and can begin a new round. 
    133133     * 
    134134     * Remarks: 
     
    148148            Condition _finished; 
    149149 
    150             public void init(uint count
     150            public void init(uint count, Mutex mutex
    151151            { 
    152152                _runningThreads = count; 
    153                 _finished = new Condition(); 
     153                _finished = new Condition(mutex); 
    154154            } 
    155155        } 
     
    169169         * efficiently solves the problem of what to do if all the first 
    170170         * generation waiters don't leave the barrier before one of the 
    171          * threads calls wait() again (i.e., starts up the next generation 
    172          * barrier). 
     171         * threads calls $(D_CODE wait()) again (i.e., starts up the next  
     172         * generation barrier). 
    173173         */ 
    174174        SubBarrier[2] _subBarrier; 
    175175 
    176176        /** 
    177          * Initialize the barrier to synchronize <count> threads. 
     177         * Initialize the barrier to synchronize $(D_PARAM count) threads. 
    178178         */ 
    179179        public this(uint count) 
     
    186186            _count = count; 
    187187            _mutex = new Mutex(); 
    188             _subBarrier[0].init(_count); 
    189             _subBarrier[1].init(_count); 
     188            _subBarrier[0].init(_count, _mutex); 
     189            _subBarrier[1].init(_count, _mutex); 
    190190        } 
    191191 
     
    202202 
    203203        /** 
    204          * Block the caller until all <count> threads have called 
    205          * Barrier.wait() and then allow all the caller threads to continue 
    206          * in parallel. 
     204         * Block the caller until all $(D_PARAM count) threads have called 
     205         * $(D_CODE Barrier.wait()) and then allow all the caller threads to  
     206         * continue in parallel. 
    207207         */ 
    208208        public void wait() 
     
    231231                while (current._runningThreads != _count) 
    232232                { 
    233                     current._finished.wait(_mutex); 
     233                    current._finished.wait(); 
    234234                } 
    235235            } 
     
    246246{ 
    247247    private import tango.util.locks.Mutex; 
     248    private import tango.util.locks.LockException; 
    248249    private import tango.core.Thread; 
    249250    private import tango.io.Stdout; 
    250     private import tango.util.locks.LockException; 
     251    private import tango.text.convert.Integer; 
     252    debug (barrier) 
     253    { 
     254        private import tango.util.log.Log; 
     255        private import tango.util.log.ConsoleAppender; 
     256        private import tango.util.log.DateLayout; 
     257    } 
    251258 
    252259    unittest 
    253260    { 
    254261        const uint MaxThreadCount   = 100; 
    255         const uint LoopsPerThread   = 100000; 
    256  
    257         Barrier allDone = new Barrier(MaxThreadCount); 
     262        const uint LoopsPerThread   = 10000; 
     263 
     264        debug (barrier) 
     265        { 
     266            scope Logger log = Log.getLogger("barrier"); 
     267 
     268            log.addAppender(new ConsoleAppender(new DateLayout())); 
     269 
     270            log.info("Barrier test"); 
     271        } 
     272 
     273        Barrier barrier = new Barrier(MaxThreadCount); 
    258274        Mutex   mutex = new Mutex(); 
    259275        uint    count = 0; 
     
    262278        void barrierTestThread() 
    263279        { 
     280            debug (barrier) 
     281            { 
     282                Logger log = Log.getLogger("barrier." ~ Thread.getThis().name()); 
     283 
     284                log.trace("Starting thread"); 
     285            } 
     286 
    264287            try 
    265288            { 
     
    269292                    // acquire the mutex before modifying it. 
    270293                    mutex.acquire(); 
     294                    // debug (barrier) 
     295                    //     log.trace("Acquired mutex"); 
    271296                    count++; 
     297                    // debug (barrier) 
     298                    //     log.trace("Releasing mutex"); 
    272299                    mutex.release(); 
    273300                } 
    274301 
    275302                // We wait for all the threads to finish counting. 
    276                 allDone.wait(); 
     303                debug (barrier) 
     304                    log.trace("Waiting on barrier"); 
     305                barrier.wait(); 
     306                debug (barrier) 
     307                    log.trace("Barrier was opened"); 
    277308 
    278309                // We make sure that all the threads exited the barrier after 
    279310                // *all* of them had finished counting. 
    280311                mutex.acquire(); 
     312                // debug (barrier) 
     313                //     log.trace("Acquired mutex"); 
    281314                if (count == MaxThreadCount * LoopsPerThread) 
    282315                { 
    283316                    ++correctCount; 
    284317                } 
     318                // debug (barrier) 
     319                //     log.trace("Releasing mutex"); 
    285320                mutex.release(); 
    286321            } 
    287322            catch (LockException e) 
    288323            { 
    289                 Stderr.formatln("Lock exception caught inside Barrier test thread:\n{0}\n", 
    290                                 e.toUtf8()); 
     324                Stderr.formatln("Lock exception caught in Barrier test thread {0}:\n{1}\n", 
     325                                Thread.getThis().name, e.toUtf8()); 
    291326            } 
    292327            catch (Exception e) 
    293328            { 
    294                 Stderr.formatln("Unexpected exception caught inside Barrier test thread:\n{0}\n", 
    295                                 e.toUtf8()); 
    296             } 
    297         } 
    298  
    299         auto group = new ThreadGroup(); 
     329                Stderr.formatln("Unexpected exception caught in Barrier test thread {0}:\n{1}\n", 
     330                                Thread.getThis().name, e.toUtf8()); 
     331            } 
     332        } 
     333 
     334        ThreadGroup group = new ThreadGroup(); 
     335        Thread      thread; 
     336        char[10]    tmp; 
    300337 
    301338        for (uint i = 0; i < MaxThreadCount; ++i) 
    302339        { 
    303             group.create(&barrierTestThread); 
    304         } 
    305  
     340            thread = new Thread(&barrierTestThread); 
     341            thread.name = "thread-" ~ format(tmp, i); 
     342 
     343            group.add(thread); 
     344            debug (barrier) 
     345                log.trace("Created thread " ~ thread.name); 
     346            thread.start(); 
     347        } 
     348 
     349        debug (barrier) 
     350            log.trace("Waiting for threads to finish"); 
    306351        group.joinAll(); 
    307352 
    308         if (count != MaxThreadCount * LoopsPerThread) 
    309         { 
    310             Stderr.formatln("The Barrier is not working properly: the counter has an incorrect value"); 
    311             assert(false); 
     353        if (count == MaxThreadCount * LoopsPerThread) 
     354        { 
     355            debug (barrier) 
     356                log.info("The Barrier test was successful"); 
     357        } 
     358        else 
     359        { 
     360            debug (barrier) 
     361            { 
     362                log.error("The Barrier is not working properly: the counter has an incorrect value"); 
     363                assert(false); 
     364            } 
     365            else 
     366            { 
     367                assert(false, "The Barrier is not working properly: the counter has an incorrect value"); 
     368            } 
    312369        } 
    313370    } 
  • trunk/tango/util/locks/Condition.d

    r1901 r2010  
    2222 * condition under the protection of a mutual exclusion lock (mutex) until 
    2323 * the condition is satisfied. That is, the mutex must have been held by 
    24  * the thread before calling wait or notifyOne/notifyAll on the condition. 
    25  * If the condition is false, a thread blocks on a condition variable and 
    26  * atomically releases the mutex that is waiting for the condition to 
    27  * change. If another thread changes the condition, it may wake up waiting 
    28  * threads by signaling the associated condition variable. The waiting 
    29  * threads, upon awakening, reacquire the mutex and re-evaluate the 
    30  * condition. 
     24 * the thread before calling $(D_CODE wait()) or $(D_CODE notify()) / 
     25 * $(D_CODE notifyAll()) on the condition. If the condition is false, a 
     26 * thread blocks on a condition variable and atomically releases the mutex 
     27 * that is waiting for the condition to change. If another thread changes 
     28 * the condition, it may wake up waiting threads by signaling the associated 
     29 * condition variable. The waiting threads, upon awakening, reacquire the 
     30 * mutex and re-evaluate the condition. 
    3131 * 
    3232 * Remarks: 
    33  * On POSIX-compatible platforms the Condition is implemented using a 
    34  * pthread_cond_t from the pthread API.The Windows API (before Windows 
    35  * Vista) does not provide a native condition variable, so it is emulated 
    36  * with a mutex, a semaphore and an event. The Windows condition variable 
    37  * emulation is based on the ACE_Condition template class from the 
    38  * $LINK2(http://www.cs.wustl.edu/~schmidt/ACE.html ACE framework). 
     33 * On POSIX-compatible platforms the $(D_CODE Condition) is implemented using a 
     34 * $(D_CODE pthread_cond_t) from the pthread API. The Windows API (before 
     35 * Windows Vista) does not provide a native condition variable, so it is 
     36 * emulated with a mutex, a semaphore and an event. The Windows condition 
     37 * variable emulation is based on the ACE_Condition template class from the 
     38 * $(LINK2 http://www.cs.wustl.edu/~schmidt/ACE.html ACE framework). 
    3939 * 
    4040 * Examples: 
     
    5151 *     while (!conditionBeingWaitedFor) 
    5252 *     { 
    53  *         success = cond.wait(lock, timeout); 
     53 *         success = cond.wait(timeout); 
    5454 *     } 
    5555 *     return success; 
     
    6565 * 
    6666 *     conditionBeingWaitedFor = true; 
    67  *     cond.notifyOne(); 
     67 *     cond.notify(); 
    6868 * } 
    6969 * --- 
     
    7777    class Condition 
    7878    { 
    79         pthread_cond_t _cond; 
     79        private pthread_cond_t  _cond; 
     80        private Mutex           _externalMutex; 
    8081 
    8182        /** 
    8283         * Initialize the condition variable. 
    8384         */ 
    84         public this() 
    85         { 
     85        public this(Mutex mutex) 
     86        in 
     87        { 
     88            assert(mutex !is null); 
     89        } 
     90        body 
     91        { 
     92            _externalMutex = mutex; 
    8693            // pthread_cond_init() will never return an error on Linux. 
    8794            pthread_cond_init(&_cond, null); 
    8895        } 
    8996 
     97        /+ IMPORTANT: 
     98           This method must remain commented out until the Mutex module that 
     99           uses each object's implicit monitor is integrated into Tango. 
     100 
     101        /** 
     102         * Initialize the condition variable with a generic object. 
     103         */ 
     104        public this(Object object) 
     105        in 
     106        { 
     107            assert(object !is null); 
     108        } 
     109        body 
     110        { 
     111            this(cast(Mutex) new MutexProxy(object)); 
     112        } 
     113        +/ 
     114 
    90115        /** 
    91116         * Implicitly destroy the condition variable. 
     
    102127 
    103128        /** 
    104          * Notify only $B(one) waiting thread that the condition is true. 
     129         * Returns a reference to the underlying mutex; 
     130         */ 
     131        public Mutex mutex() 
     132        { 
     133            return _externalMutex; 
     134        } 
     135 
     136        /** 
     137         * Notify only $(B one) waiting thread that the condition is true. 
    105138         * 
    106139         * Remarks: 
    107140         * The external mutex must be locked before calling this method. 
    108141         */ 
    109         void notifyOne() 
     142        public void notify() 
    110143        { 
    111144            // pthread_cond_signal() will never return an error on Linux, but 
     
    120153 
    121154        /** 
    122          * Notify $B(all) waiting threads that the condition is true. 
     155         * Notify $(B all) waiting threads that the condition is true. 
    123156         * 
    124157         * Remarks: 
    125158         * The external mutex must be locked before calling this method. 
    126159         */ 
    127         void notifyAll() 
     160        public void notifyAll() 
    128161        { 
    129162            // pthread_cond_broadcast() will never return an error on Linux, 
     
    138171 
    139172        /** 
    140          * Block on the condition
     173         * Block until the condition is notified from another thread
    141174         * 
    142175         * Remarks: 
    143176         * The external mutex must be locked before calling this method. 
    144177         */ 
    145         void wait(Mutex externalMutex) 
    146         in 
    147         { 
    148             assert(externalMutex !is null); 
    149         } 
    150         body 
     178        public void wait() 
    151179        { 
    152180            // pthread_cond_wait() will never return an error on Linux, 
    153181            // but it may on other platforms. 
    154             int rc = pthread_cond_wait(&_cond, &externalMutex._mutex); 
     182            int rc = pthread_cond_wait(&_cond, _externalMutex.mutex()); 
    155183 
    156184            if (rc != 0) 
     
    162190        /** 
    163191         * Block on the condition, or until the specified (relative) amount 
    164          * of time has passed. If $D_PARAM(timeout) == $D_CODE(Interval.max) 
     192         * of time has passed. If ($D_PARAM timeout) == $(D_CODE Interval.max) 
    165193         * there is no timeout. 
    166194         * 
     
    171199         * The external mutex must be locked before calling this method. 
    172200         */ 
    173         bool wait(Mutex externalMutex, Interval timeout) 
    174         in 
    175         { 
    176             assert(externalMutex !is null); 
    177         } 
    178         body 
     201        public bool wait(Interval timeout) 
    179202        { 
    180203            if (timeout == Interval.max) 
    181204            { 
    182                 wait(externalMutex); 
     205                wait(); 
    183206                return true; 
    184207            } 
     
    188211                timespec ts; 
    189212 
    190                 rc = pthread_cond_timedwait(&_cond, &externalMutex._mutex
     213                rc = pthread_cond_timedwait(&_cond, _externalMutex.mutex()
    191214                                            toTimespec(&ts, toAbsoluteTime(timeout))); 
    192215 
     
    209232 
    210233        /** 
    211          * Check the 'errorCode' argument against possible errno values and 
    212          * throw an exception with the description of the error. 
     234         * Check the $(D_PARAM errorCode) argument against possible values 
     235         * of $(D_CODE SysError.lastCode()) and throw an exception with the 
     236         * description of the error. 
    213237         * 
    214238         * Params: 
    215          * errorCode    = errno value; must not be 0. 
     239         * errorCode    = SysError.lastCode() value; must not be 0. 
    216240         * file         = name of the source file where the check is being 
    217241         *                made; you would normally use __FILE__ for this 
     
    223247         * Throws: 
    224248         * AlreadyLockedException when the mutex has already been locked by 
    225          * another thread (EBUSY); DeadlockException when the mutex has already 
    226          * been locked by the calling thread (EDEADLK); InvalidMutexException 
    227          * when the mutex has not been properly initialized (EINVAL)
    228          * MutexOwnerException when the calling thread does not own the mutex 
    229          * (EPERM); LockException for any of the other cases in which errno is 
    230          * not 0. 
    231          */ 
    232         protected void checkError(int errorCode, char[] file, uint line) 
     249         * another thread; DeadlockException when the mutex has already 
     250         * been locked by the calling thread; InvalidMutexException 
     251         * when the mutex has not been properly initialized
     252         * MutexOwnerException when the calling thread does not own the mutex; 
     253         * LockException for any of the other cases in which 
     254         * $(D_PARAM errorCode) is not 0. 
     255         */ 
     256        protected void checkError(uint errorCode, char[] file, uint line) 
    233257        in 
    234258        { 
     
    271295        private Event       _waitersDone; 
    272296        private bool        _wasBroadcast = false; 
     297        private Mutex       _externalMutex; 
    273298 
    274299        /** 
    275300         * Initialize the condition variable. 
    276301         */ 
    277         public this() 
     302        public this(Mutex mutex) 
     303        in 
     304        { 
     305            assert(mutex !is null); 
     306        } 
     307        body 
    278308        { 
    279309            _wasBroadcast = 0; 
     
    288318 
    289319            _waitersDone = new Event(); 
    290         } 
     320 
     321            _externalMutex = mutex; 
     322        } 
     323 
     324        /+ IMPORTANT: 
     325           This method must remain commented out until the Mutex module that 
     326           uses each object's implicit monitor is integrated into Tango. 
     327 
     328        /** 
     329         * Initialize the condition variable with a generic Object to be used  
     330         * as a mutex. 
     331         */ 
     332        public this(Object object) 
     333        in 
     334        { 
     335            assert(object !is null); 
     336        } 
     337        body 
     338        { 
     339            this(cast(Mutex) new MutexProxy(object)); 
     340        } 
     341        +/ 
    291342 
    292343        /** 
     
    295346        public ~this() 
    296347        { 
     348            _externalMutex = null; 
    297349            delete _waitersDone; 
    298350            delete _waitersLock; 
     
    301353 
    302354        /** 
    303          * Notify only $B(one) waiting thread that the condition is true. 
     355         * Notify only $(B one) waiting thread that the condition is true. 
    304356         * 
    305357         * Remarks: 
    306358         * The external mutex must be locked before calling this method. 
    307359         */ 
    308         void notifyOne() 
     360        public void notify() 
    309361        { 
    310362            // If there aren't any waiters, then this is a no-op.  Note that 
    311             // this function *must* be called with the <externalMutex> held 
     363            // this function *must* be called with the 'externalMutex' held 
    312364            // since otherwise there is a race condition that can lead to the 
    313             // lost wakeup bug... This is needed to ensure that the <_waitersCount> 
     365            // lost wakeup bug... This is needed to ensure that the '_waitersCount' 
    314366            // value is not in an inconsistent internal state while being 
    315367            // updated by another thread. 
     
    325377 
    326378        /** 
    327          * Notify $B(all) waiting threads that the condition is true. 
     379         * Notify $(B all) waiting threads that the condition is true. 
    328380         * 
    329381         * Remarks: 
    330382         * The external mutex must be locked before calling this method. 
    331383         */ 
    332         void notifyAll() 
     384        public void notifyAll() 
    333385        { 
    334386            bool hasWaiters = false; 
     
    336388            // The <externalMutex> must be locked before this call is made. 
    337389 
    338             // This is needed to ensure that <_waitersCount> and <_wasBroadcast> are 
     390            // This is needed to ensure that '_waitersCount' and '_wasBroadcast' are 
    339391            // consistent relative to each other. 
    340392            _waitersLock.acquire(); 
     
    345397                // Record the fact that we are broadcasting.  This helps the 
    346398                // Condition.wait() method know how to optimize itself.  Be 
    347                 // sure to set this with the <_waitersLock> held. 
     399                // sure to set this with the '_waitersLock' held. 
    348400                _wasBroadcast   = true; 
    349401                hasWaiters      = true; 
     
    363415                _waitersDone.wait(); 
    364416 
    365                 // This is okay, even without the <_waitersLock> held, because 
     417                // This is okay, even without the '_waitersLock' held, because 
    366418                // no other waiter threads can wake up to access it. 
    367419                _wasBroadcast = false;