Re: interthread communication
*****
Key here is that you have two separate conditions: you need a loop to han=
dle incoming
packets (the message pump of your UI thread) and you need a way to send d=
ata continuously
to a device (another thread!). I would probably use a semaphore here, =
see my essay on
semaphores. But instead of blocking INFINITE on the semaphore, the wri=
ter thread will
block for 0 ms. So if there is something in the queue, it will dequeue=
it, otherwise it
will return WAIT_TIMEOUT and you get to re-send the existing message. =
So now I understand
the "if no new input" line. That would become a WFMO on the semaphore =
and the shutdown
event. But you have a two-thread problem here which you were trying to=
reduce to a
one-thread problem.
joe
****
that`s perfect that you understand the problem. I also know what I
want but I don`t know how I can acchieve this exaclty.
I need two user threads: The first thread will get and collect the
pointers to the CbyteArrays and store these arrays in a list?
CSerialCollectData : public CWinThread
{
Queue q;
long count; //semaphore count
BOOL firstTimeCall; //set to TRUE in the constructor
};
void CSerialData::OnGetNewData(WPARAM wParam, LPARAM lParam)
{
if(firstTimeCall)
{
//start second thread for tx serial packets
firstTimeCall = FALSE;
CWinThread * thread = AfxBeginThread(threadStart, //
thread function
this, //
thread function parameter
THREAD_PRIORITY_NORMAL, //
priority
0, //
use default stack size
CREATE_SUSPENDED); //
not running
thread->ResumeThread();
//any additional recommendations to verfiy that the thread is
already running?
}
CByteArray * data = (CByteArray *)wParam;
if(!q.AddTail(data))
{
//error queue full
return;
}
long n = InterlockedIncrement(&count);
delete [] data;
}
That`s all I have to do to collect the data in the queue for the
second thread? Is it true, that I can already delete the buffer "data"
after adding it on the queue?
The second thread should start when the first ethernet frame will be
received (firstTimeCall).
void CSerialData::threadStart(LPVOID me)
{
//start
CSerialData *start = (CSerialData *)me;
return (start->run());
}
BOOL CSerialData::run()
{
//tx serial data
DWORD bytesWritten;
while(1)
{
LPVOID p = q.RemoveHead();
//how is it possible to know how many packets included in this
list??? because if the list is empty + shutdown event > thread will
close
CByteArray *data = ( CByteArray *)p;
long n = InterlockedDecrement(&count);
FT_Write(ftHandle, data->GetData(), 1, &bytesWritten);
WaitForSingleObject(hEvent,0seconds);
}
}
I hope there`s something right in the above code. If I`m right, with
this solution the thread ( CSerialData::run) will be send some data if
some data is available in the queue q. But two things are not
supported so far; the possibility to see if there are more than one
item available in the queue q and the part waiting until the hEvent
occured.
Using a second UI-thread I can recall the specific function sending
the data to the serial port by a PostThreadMessage().
void CSerialData::OnGetNewData(WPARAM wParam, LPARAM lParam)
{
CByteArray * data = (CByteArray *)wParam;
if(!q.AddTail(data))
{
//error queue full
return;
}
long n = InterlockedIncrement(&count);
::PostThreadMessage(threadWriterID, UWM_NEW_DATA_AVAIL, 0, 0);
}
void CSerialWrite::OnNewDataAvail(wParam, lParam)
{
if(! WAIT_TIMEOUT)
{
//new data can be txd
LPVOID p = q.RemoveHead();
CByteArray *data = ( CByteArray *)p;
long n = InterlockedDecrement(&count);
FT_Write(ftHandle, data->GetData(), 1, &bytesWritten);
WaitForSingleObject(hEvent,0seconds);
WAIT_TIMEOUT = TRUE;
}
else
{
//waiting for the CTS_High event -> sending a PostThreadMessage
to this function???
}
}
best regards
Hans