Boost logo

Boost :

From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-01-02 12:44:37

Roland wrote:

> Using this I´ll post the following code.
> (Which is a blocking, but cancelable write function.)
> Say you have a port object, whose functions are protected by a monitor.
> (This is for the Windows API.)
> size_t tcp_port::write(const byte* p, size_t c)
> {
> DWORD dw;
> MSG msg;
> HANDLE rgev[2];
> DWORD ev;
> lock lk(monitor);
> if (!WriteFile(m_h, p, c, &dw, &m_ovWrite)) {
> if (ERROR_IO_PENDING == GetLastError()) {
> regev[0] = m_evWrite;
> regev[1] = m_evCancel;
> while (TRUE) {
> // the following three lines are meant to be similar to the call of the wait function of a condition
> lk.unlock(); // Note 1
> ev = MsgWaitForMultipleObjects(2, rgev, FALSE, INFINITE, QS_ALLINPUT);
> lk.lock(); // Note 2
> if (WAIT_OBJECT_0 == ev) {
> if (!GetOverlappedResult(m_h, &ovWrite, &dw, TRUE))
> return 0;
> else
> break;
> } else if (WAIT_OBJECT_0+1 == ev) {
> CancelIo(m_h);
> return 0;
> }
> ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
> }
> }
> else
> retirn 0
> }
> *((unsigned __int64*)&(m_ovWrite.Offset)) += dw;
> return dw;
> }
> What I am beeing afraid is nopw, is that places "Note1" and "Note2" might introduce a race condition,
> when another call to my port object goes in between.

The simplest way of avoiding that is simply not to unlock the monitor
mutex. The reason the wait function of a condition variable unlocks the
mutex is so that another thread can obtain the mutex, perform some
operation, then signal that the condition has become true. Since in this
case the write operation doesn't need to obtain the mutex in order to
complete, there's no need to unlock it. Unless there are other reasons I
don't know about?

> As far as I can understand, this normally is
> avoided through the while loop that belongs to the "condition variable pattern".

Not really. The while loop handles the case where a thread "wakes up"
but the condition isn't really true yet; it "puts it back to sleep" by
making it wait some more.

> Since such blocking calls to the operating system are similar in semantics to "cond.wait(lk)" (aren't they?)

Not really, for the reason I mentioned above.

> I was looking for some systematic way to handle them in a similar way. I also think that using the library
> to write platform independent code, it will be necessary to deal with this question at the lowest level possible
> to avoid a lot of #ifdefs later on. Ideally I would like to see much less WinAPI calls in my function than I do now.
> I am still not sure if I was able to expain my point, but I hope you will be patient enough
> to ask me further questions that will help me to be more precise.
> Roland
> _______________________________________________
> Unsubscribe & other changes:

Boost list run by bdawes at, gregod at, cpdaniel at, john at