bool CReaderWriterLockNonReentrance::AcquireWriterLock(DWORD dwTimeout) { bool blCanWrite ; EnterCS(); if(0 == (m_iNumOfWriter | m_iNumOfReaderEntered)) { ++m_iNumOfWriter; blCanWrite = TRUE; } else if(0 == dwTimeout) { blCanWrite = FALSE; } else { blCanWrite = _WriterWaitAndLeaveCSIfSuccess(dwTimeout); if(blCanWrite) { return TRUE; } } LeaveCS(); return blCanWrite; }
bool CReaderWriterLockNonReentrance::AcquireReaderLock(DWORD dwTimeout) { bool blCanRead; EnterCS(); if(0 == m_iNumOfWriter) { // Enter successful without wait ++m_iNumOfReaderEntered; blCanRead = TRUE; } else { blCanRead = (dwTimeout)? _ReaderWait(dwTimeout) : FALSE; } LeaveCS(); return blCanRead; }
bool CReaderWriterLockNonReentrance::_WriterWaitAndLeaveCSIfSuccess(DWORD dwTimeout) { //EnterCS(); _ASSERT(0 != dwTimeout); // Increase Writer-counter & reset Reader-event if necessary INT _iNumOfWriter = ++m_iNumOfWriter; if( (1 == _iNumOfWriter) && (NULL != m_hSafeToReadEvent) ) { ResetEvent(m_hSafeToReadEvent); } if(NULL == m_hSafeToWriteEvent) { m_hSafeToWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } LeaveCS(); bool blCanWrite = (WAIT_OBJECT_0 == WaitForSingleObject(m_hSafeToWriteEvent, dwTimeout)); if(FALSE == blCanWrite) { // Undo what we changed after timeout EnterCS(); if(0 == --m_iNumOfWriter) { CloseHandle(m_hSafeToWriteEvent); m_hSafeToWriteEvent = NULL; if(0 == m_iNumOfReaderEntered) { // Although it was timeout, it's still safe to be writer now ++m_iNumOfWriter; LeaveCS(); blCanWrite = TRUE; } else if(m_hSafeToReadEvent) { SetEvent(m_hSafeToReadEvent); } } } return blCanWrite; }
bool_t EventDeliver( WSSvr_st *st, WSSvr_Window *w, WS_Event *ev, bool_t block) { Event_Val val; if(w->wid == ROOT_WINDOW) { HandleRootWindowEvent(st, ev); } ev->w = w->wid; if((!block) || (Pvs(thd) == st->event_thread)) { /* We can't block here, so optionally throw this event away */ Threads$EnterCS(Pvs(thds), False); val = SQ_READ(st->free_event_sq); if(EC_READ(st->free_event_ec) < val) { /* We would have to block - refuse the event */ Threads$LeaveCS(Pvs(thds)); return False; } else { val = SQ_TICKET(st->free_event_sq); Threads$LeaveCS(Pvs(thds)); } } else { val = SQ_TICKET(st->free_event_sq); } EC_AWAIT(st->free_event_ec, val); val = val % NUM_EVENT_RECS; st->events[val] = *ev; EC_ADVANCE(st->valid_event_ec, 1); return True; }
void EventThread(WSSvr_st *st) { Event_Val val = 0; WS_Event *ev; st->event_thread = Pvs(thd); while(1) { WSSvr_Window *w; EC_AWAIT(st->valid_event_ec, val + 1); ev = &st->events[val % NUM_EVENT_RECS]; w = &st->window[ev->w]; if(ev->d.tag == WS_EventType_Expose) { /* Get the exposure rectangle */ Threads$EnterCS(Pvs(thds), False); ev->d.u.Expose = w->expose_rect; w->expose_due = False; Threads$LeaveCS(Pvs(thds)); } if(ev->d.tag == WS_EventType_Mouse) { /* Try coalescing mouse events */ while(EC_READ(st->valid_event_ec) > (val+1)) { WS_Event *ev_next; val++; ev_next = &st->events[val % NUM_EVENT_RECS]; /* See if this is a mouse event in the same window */ if((ev_next->d.tag == WS_EventType_Mouse) && (ev_next->d.u.Mouse.buttons == ev->d.u.Mouse.buttons)) { /* Free old event */ EC_ADVANCE(st->free_event_ec, 1); /* Point at new event */ ev = ev_next; } else { /* Push this event back */ val--; break; } } } WM$HandleEvent(st->wm, ev, w->owner ? (&w->owner->wsf_cl) : NULL); /* Free event */ EC_ADVANCE(st->free_event_ec, 1); val++; #if 0 if(st->need_refocus) { MU_LOCK(&st->mu); Refocus(st); MU_RELEASE(&st->mu); } #endif } }
bool CReaderWriterLockNonReentrance::_ReaderWait(DWORD dwTimeout) throw() { bool blCanRead; ++m_iNumOfReaderWaiting; if(NULL == m_hSafeToReadEvent) { m_hSafeToReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } if(INFINITE == dwTimeout) // INFINITE is a special value { do { LeaveCS(); WaitForSingleObject(m_hSafeToReadEvent, INFINITE); // There might be one or more Writers entered, that's // why we need DO-WHILE loop here EnterCS(); } while(0 != m_iNumOfWriter); ++m_iNumOfReaderEntered; blCanRead = TRUE; } else { LeaveCS(); DWORD const dwBeginTime = GetTickCount(); DWORD dwConsumedTime = 0; while(TRUE) { blCanRead = (WAIT_OBJECT_0 == WaitForSingleObject(m_hSafeToReadEvent, dwTimeout - dwConsumedTime)); EnterCS(); if(0 == m_iNumOfWriter) { // Regardless timeout or not, there is no Writer // So it's safe to be Reader right now ++m_iNumOfReaderEntered; blCanRead = TRUE; break; } if(FALSE == blCanRead) { // Timeout after waiting break; } // There are some Writers have just entered // So leave CS and prepare to try again LeaveCS(); dwConsumedTime = GetTickCount() - dwBeginTime; if(dwConsumedTime > dwTimeout) { // Don't worry why the code here looks stupid // Because this case rarely happens, it's better // to optimize code for the usual case blCanRead = FALSE; EnterCS(); break; } } } if(0==--m_iNumOfReaderWaiting) { CloseHandle(m_hSafeToReadEvent); m_hSafeToReadEvent = NULL; } return blCanRead; }
bool CReaderWriterLockNonReentrance::UpgradeToWriterLock(DWORD dwTimeout) throw() { EnterCS(); return _UpgradeToWriterLockAndLeaveCS(dwTimeout); }
void CReaderWriterLockNonReentrance::DowngradeFromWriterLock() { EnterCS(); _WriterRelease(TRUE); LeaveCS(); }
void CReaderWriterLockNonReentrance::ReleaseWriterLock() { EnterCS(); _WriterRelease(FALSE); LeaveCS(); }