Re: MT Design Question
"Joshua Maurice" <joshuamaurice@gmail.com> wrote in message
news:c56c7bf9-86d4-44dc-a4fa-04ea55227325@s17g2000prh.googlegroups.com...
On Aug 28, 9:32 pm, "joe" <jc1...@att.net> wrote:
Joshua Maurice wrote:
On Aug 26, 1:35 pm, "joe" <jc1...@att.net> wrote:
See the Windows API WaitForMultipleObjects. This kind of stuff is
trivial in Windows.
This is sort of a pet peeve of mine, but please don't suggest to
anyone to actually directly use the windows threading API if at all
possible. It's borked, at least for windows XP and earlier, as it
lacks condition variables.
Well, ya see, me a programmer on Wintel has no need for UNIX/pthreads. I
am not a computer scientist like you are.
Could you write up a simple example of multiple producers and multiple
consumers without conditions variables?
Here is a simple multi-producer/consumer queue using a single manual reset
event for waiters:
<pseudo-code sketch>
_________________________________________________________
struct node
{
node* m_next;
};
struct queue
{
node* m_head; // = NULL;
node* m_tail;
HANDLE m_waitset; // manual reset event; set to false
CRITICAL_SECTION m_lock;
void push(node* n)
{
n->m_next = NULL;
EnterCriticalSection(&m_lock);
if (! m_head)
{
m_head = n;
SetEvent(m_waitset);
}
else
{
m_tail->m_next = n;
}
m_tail = n;
LeaveCriticalSection(&m_lock);
}
node* pop()
{
node* n;
EnterCriticalSection(&m_lock);
while (! (n = m_head))
{
LeaveCriticalSection(&m_lock);
WaitForSingleObject(m_waitset, INFINITE);
EnterCriticalSection(&m_lock);
}
if (! (m_head = n->m_next))
{
ResetEvent(m_waitset);
}
LeaveCriticalSection(&m_lock);
return n;
}
};
_________________________________________________________
Do you have any nontrivial
examples where windows event classes result in simpler and more
efficient code than the condition variable alternative?
An event can make some code simpler. Take a slow path for, say a simple
mutex algorithm:
<event version - pseudo-code sketch>
_________________________________________________________
struct mutex
{
LONG m_state; // = 0
HANDLE m_waitset; // auto reset event; set to false
void lock()
{
if (InterlockedExchange(&m_state, 1))
{
while (InterlockedExchange(&m_state, 2))
{
WaitForSingleObject(m_waitset, INFINITE);
}
}
}
void unlock()
{
if (InterlockedExchange(&m_state, 0) == 2)
{
SetEvent(m_waitset);
}
}
};
_________________________________________________________
If Windows _only_ had condition variables then I would have to do something
like this:
<condvarversion - pseudo-code>
_________________________________________________________
struct mutex
{
LONG m_state; // = 0
BOOL m_set; // = FALSE
COND_MUTEX m_mutex;
COND_VAR m_cond;
void lock()
{
if (InterlockedExchange(&m_state, 1))
{
while (InterlockedExchange(&m_state, 2))
{
m_mutex.lock();
while (! m_set) m_cond.wait(m_mutex);
m_set = false;
m_mutex.unlock();
}
}
}
void unlock()
{
if (InterlockedExchange(&m_state, 0) == 2)
{
m_mutex.lock();
m_set = true;
m_mutex.unlock();
m_cond.signal();
}
}
};
_________________________________________________________
I would say that is more complex than using a single kernel event.
My claim is
that this is inordinately difficult compared to the much simpler
solution with condition variables.
[...]