@@ -96,26 +96,28 @@ class Condition
9696 {
9797 version (Windows )
9898 {
99- static if (is (Q == Condition ))
99+ auto self = cast (Condition ) this ;
100+ alias HANDLE_TYPE = void * ;
101+ self.m_blockLock = cast (HANDLE_TYPE ) CreateSemaphoreA( null , 1 , 1 , null );
102+ if ( self.m_blockLock == self.m_blockLock.init )
103+ throw staticError! AssertError (" Unable to initialize condition" , __FILE__ , __LINE__ );
104+ scope (failure) CloseHandle ( cast (void * ) self.m_blockLock );
105+
106+ self.m_blockQueue = cast (HANDLE_TYPE ) CreateSemaphoreA( null , 0 , int .max, null );
107+ if ( self.m_blockQueue == self.m_blockQueue.init )
108+ throw staticError! AssertError (" Unable to initialize condition" , __FILE__ , __LINE__ );
109+ scope (failure) CloseHandle ( cast (void * ) self.m_blockQueue );
110+
111+ InitializeCriticalSection( cast (RTL_CRITICAL_SECTION * ) &self.m_unblockLock );
112+ static if (is (M == shared Mutex ))
100113 {
101- alias HANDLE_TYPE = void * ;
114+ import core.atomic : atomicLoad;
115+ self.m_assocMutex = cast (Mutex ) atomicLoad(m);
102116 }
103117 else
104118 {
105- alias HANDLE_TYPE = shared ( void * ) ;
119+ self.m_assocMutex = m ;
106120 }
107- m_blockLock = cast (HANDLE_TYPE ) CreateSemaphoreA( null , 1 , 1 , null );
108- if ( m_blockLock == m_blockLock.init )
109- throw staticError! AssertError (" Unable to initialize condition" , __FILE__ , __LINE__ );
110- scope (failure) CloseHandle ( cast (void * ) m_blockLock );
111-
112- m_blockQueue = cast (HANDLE_TYPE ) CreateSemaphoreA( null , 0 , int .max, null );
113- if ( m_blockQueue == m_blockQueue.init )
114- throw staticError! AssertError (" Unable to initialize condition" , __FILE__ , __LINE__ );
115- scope (failure) CloseHandle ( cast (void * ) m_blockQueue );
116-
117- InitializeCriticalSection( cast (RTL_CRITICAL_SECTION * ) &m_unblockLock );
118- m_assocMutex = m;
119121 }
120122 else version (Posix )
121123 {
@@ -419,183 +421,167 @@ private:
419421 bool timedWait (this Q)( DWORD timeout )
420422 if (is (Q == Condition ) || is (Q == shared Condition ))
421423 {
422- static if ( is (Q == Condition ) )
424+ auto op ( string o, T, V1 )( ref T val, V1 mod )
423425 {
424- auto op (string o, T, V1 )(ref T val, V1 mod)
425- {
426- return mixin (" val " ~ o ~ " mod" );
427- }
428- }
429- else
430- {
431- auto op (string o, T, V1 )(ref shared T val, V1 mod)
432- {
433- import core.atomic : atomicOp;
434- return atomicOp! o(val, mod);
435- }
426+ return mixin (" val " ~ o ~ " mod" );
436427 }
437428
429+ // The Windows condition implementation protects these fields with
430+ // Win32 synchronization primitives that the compiler cannot model.
431+ auto self = cast (Condition ) this ;
438432 int numSignalsLeft;
439433 int numWaitersGone;
440434 DWORD rc;
441435
442- rc = WaitForSingleObject( cast (HANDLE ) m_blockLock, INFINITE );
436+ rc = WaitForSingleObject( cast (HANDLE ) self. m_blockLock, INFINITE );
443437 assert ( rc == WAIT_OBJECT_0 );
444438
445- op! " +=" (m_numWaitersBlocked, 1 );
439+ op! " +=" (self. m_numWaitersBlocked, 1 );
446440
447- rc = ReleaseSemaphore( cast (HANDLE ) m_blockLock, 1 , null );
441+ rc = ReleaseSemaphore( cast (HANDLE ) self. m_blockLock, 1 , null );
448442 assert ( rc );
449443
450- m_assocMutex.unlock();
451- scope (failure) m_assocMutex.lock();
444+ self. m_assocMutex.unlock();
445+ scope (failure) self. m_assocMutex.lock();
452446
453- rc = WaitForSingleObject( cast (HANDLE ) m_blockQueue, timeout );
447+ rc = WaitForSingleObject( cast (HANDLE ) self. m_blockQueue, timeout );
454448 assert ( rc == WAIT_OBJECT_0 || rc == WAIT_TIMEOUT );
455449 bool timedOut = (rc == WAIT_TIMEOUT );
456450
457- EnterCriticalSection( &m_unblockLock );
458- scope (failure) LeaveCriticalSection ( &m_unblockLock );
451+ EnterCriticalSection( &self. m_unblockLock );
452+ scope (failure) LeaveCriticalSection ( &self. m_unblockLock );
459453
460- if ( (numSignalsLeft = m_numWaitersToUnblock) != 0 )
454+ if ( (numSignalsLeft = self. m_numWaitersToUnblock) != 0 )
461455 {
462456 if ( timedOut )
463457 {
464458 // timeout (or canceled)
465- if ( m_numWaitersBlocked != 0 )
459+ if ( self. m_numWaitersBlocked != 0 )
466460 {
467- op! " -=" (m_numWaitersBlocked, 1 );
461+ op! " -=" (self. m_numWaitersBlocked, 1 );
468462 // do not unblock next waiter below (already unblocked)
469463 numSignalsLeft = 0 ;
470464 }
471465 else
472466 {
473467 // spurious wakeup pending!!
474- m_numWaitersGone = 1 ;
468+ self. m_numWaitersGone = 1 ;
475469 }
476470 }
477- if ( op! " -=" (m_numWaitersToUnblock, 1 ) == 0 )
471+ if ( op! " -=" (self. m_numWaitersToUnblock, 1 ) == 0 )
478472 {
479- if ( m_numWaitersBlocked != 0 )
473+ if ( self. m_numWaitersBlocked != 0 )
480474 {
481475 // open the gate
482- rc = ReleaseSemaphore( cast (HANDLE ) m_blockLock, 1 , null );
476+ rc = ReleaseSemaphore( cast (HANDLE ) self. m_blockLock, 1 , null );
483477 assert ( rc );
484478 // do not open the gate below again
485479 numSignalsLeft = 0 ;
486480 }
487- else if ( (numWaitersGone = m_numWaitersGone) != 0 )
481+ else if ( (numWaitersGone = self. m_numWaitersGone) != 0 )
488482 {
489- m_numWaitersGone = 0 ;
483+ self. m_numWaitersGone = 0 ;
490484 }
491485 }
492486 }
493- else if ( op! " +=" (m_numWaitersGone, 1 ) == int .max / 2 )
487+ else if ( op! " +=" (self. m_numWaitersGone, 1 ) == int .max / 2 )
494488 {
495489 // timeout/canceled or spurious event :-)
496- rc = WaitForSingleObject( cast (HANDLE ) m_blockLock, INFINITE );
490+ rc = WaitForSingleObject( cast (HANDLE ) self. m_blockLock, INFINITE );
497491 assert ( rc == WAIT_OBJECT_0 );
498492 // something is going on here - test of timeouts?
499- op! " -=" (m_numWaitersBlocked, m_numWaitersGone);
500- rc = ReleaseSemaphore( cast (HANDLE ) m_blockLock, 1 , null );
493+ op! " -=" (self. m_numWaitersBlocked, self. m_numWaitersGone);
494+ rc = ReleaseSemaphore( cast (HANDLE ) self. m_blockLock, 1 , null );
501495 assert ( rc == WAIT_OBJECT_0 );
502- m_numWaitersGone = 0 ;
496+ self. m_numWaitersGone = 0 ;
503497 }
504498
505- LeaveCriticalSection( &m_unblockLock );
499+ LeaveCriticalSection( &self. m_unblockLock );
506500
507501 if ( numSignalsLeft == 1 )
508502 {
509503 // better now than spurious later (same as ResetEvent)
510504 for ( ; numWaitersGone > 0 ; -- numWaitersGone )
511505 {
512- rc = WaitForSingleObject( cast (HANDLE ) m_blockQueue, INFINITE );
506+ rc = WaitForSingleObject( cast (HANDLE ) self. m_blockQueue, INFINITE );
513507 assert ( rc == WAIT_OBJECT_0 );
514508 }
515509 // open the gate
516- rc = ReleaseSemaphore( cast (HANDLE ) m_blockLock, 1 , null );
510+ rc = ReleaseSemaphore( cast (HANDLE ) self. m_blockLock, 1 , null );
517511 assert ( rc );
518512 }
519513 else if ( numSignalsLeft != 0 )
520514 {
521515 // unblock next waiter
522- rc = ReleaseSemaphore( cast (HANDLE ) m_blockQueue, 1 , null );
516+ rc = ReleaseSemaphore( cast (HANDLE ) self. m_blockQueue, 1 , null );
523517 assert ( rc );
524518 }
525- m_assocMutex.lock();
519+ self. m_assocMutex.lock();
526520 return ! timedOut;
527521 }
528522
529523
530524 void notify_ (this Q)( bool all )
531525 if (is (Q == Condition ) || is (Q == shared Condition ))
532526 {
533- static if ( is (Q == Condition ) )
527+ auto op ( string o, T, V1 )( ref T val, V1 mod )
534528 {
535- auto op (string o, T, V1 )(ref T val, V1 mod)
536- {
537- return mixin (" val " ~ o ~ " mod" );
538- }
539- }
540- else
541- {
542- auto op (string o, T, V1 )(ref shared T val, V1 mod)
543- {
544- import core.atomic : atomicOp;
545- return atomicOp! o(val, mod);
546- }
529+ return mixin (" val " ~ o ~ " mod" );
547530 }
548531
532+ // The Windows condition implementation protects these fields with
533+ // Win32 synchronization primitives that the compiler cannot model.
534+ auto self = cast (Condition ) this ;
549535 DWORD rc;
550536
551- EnterCriticalSection( &m_unblockLock );
552- scope (failure) LeaveCriticalSection ( &m_unblockLock );
537+ EnterCriticalSection( &self. m_unblockLock );
538+ scope (failure) LeaveCriticalSection ( &self. m_unblockLock );
553539
554- if ( m_numWaitersToUnblock != 0 )
540+ if ( self. m_numWaitersToUnblock != 0 )
555541 {
556- if ( m_numWaitersBlocked == 0 )
542+ if ( self. m_numWaitersBlocked == 0 )
557543 {
558- LeaveCriticalSection( &m_unblockLock );
544+ LeaveCriticalSection( &self. m_unblockLock );
559545 return ;
560546 }
561547 if ( all )
562548 {
563- op! " +=" (m_numWaitersToUnblock, m_numWaitersBlocked);
564- m_numWaitersBlocked = 0 ;
549+ op! " +=" (self. m_numWaitersToUnblock, self. m_numWaitersBlocked);
550+ self. m_numWaitersBlocked = 0 ;
565551 }
566552 else
567553 {
568- op! " +=" (m_numWaitersToUnblock, 1 );
569- op! " -=" (m_numWaitersBlocked, 1 );
554+ op! " +=" (self. m_numWaitersToUnblock, 1 );
555+ op! " -=" (self. m_numWaitersBlocked, 1 );
570556 }
571- LeaveCriticalSection( &m_unblockLock );
557+ LeaveCriticalSection( &self. m_unblockLock );
572558 }
573- else if ( m_numWaitersBlocked > m_numWaitersGone )
559+ else if ( self. m_numWaitersBlocked > self. m_numWaitersGone )
574560 {
575- rc = WaitForSingleObject( cast (HANDLE ) m_blockLock, INFINITE );
561+ rc = WaitForSingleObject( cast (HANDLE ) self. m_blockLock, INFINITE );
576562 assert ( rc == WAIT_OBJECT_0 );
577- if ( 0 != m_numWaitersGone )
563+ if ( 0 != self. m_numWaitersGone )
578564 {
579- op! " -=" (m_numWaitersBlocked, m_numWaitersGone);
580- m_numWaitersGone = 0 ;
565+ op! " -=" (self. m_numWaitersBlocked, self. m_numWaitersGone);
566+ self. m_numWaitersGone = 0 ;
581567 }
582568 if ( all )
583569 {
584- m_numWaitersToUnblock = m_numWaitersBlocked;
585- m_numWaitersBlocked = 0 ;
570+ self. m_numWaitersToUnblock = self. m_numWaitersBlocked;
571+ self. m_numWaitersBlocked = 0 ;
586572 }
587573 else
588574 {
589- m_numWaitersToUnblock = 1 ;
590- op! " -=" (m_numWaitersBlocked, 1 );
575+ self. m_numWaitersToUnblock = 1 ;
576+ op! " -=" (self. m_numWaitersBlocked, 1 );
591577 }
592- LeaveCriticalSection( &m_unblockLock );
593- rc = ReleaseSemaphore( cast (HANDLE ) m_blockQueue, 1 , null );
578+ LeaveCriticalSection( &self. m_unblockLock );
579+ rc = ReleaseSemaphore( cast (HANDLE ) self. m_blockQueue, 1 , null );
594580 assert ( rc );
595581 }
596582 else
597583 {
598- LeaveCriticalSection( &m_unblockLock );
584+ LeaveCriticalSection( &self. m_unblockLock );
599585 }
600586 }
601587
0 commit comments