different strategy for mutex in protocol class, fix for sending jitter buffer change message when no connection is established

This commit is contained in:
Volker Fischer 2006-03-08 18:44:21 +00:00
parent 736a7b043a
commit a4610ef287
3 changed files with 145 additions and 121 deletions

View file

@ -87,7 +87,14 @@ public:
int GetSockBufSize() { return SockBuf.GetSize(); } int GetSockBufSize() { return SockBuf.GetSize(); }
// network protocol interface // network protocol interface
void CreateJitBufMes ( const int iJitBufSize ) { Protocol.CreateJitBufMes ( iJitBufSize ); } void CreateJitBufMes ( const int iJitBufSize )
{
if ( IsConnected() )
{
Protocol.CreateJitBufMes ( iJitBufSize );
}
}
void CreateReqJitBufMes() { Protocol.CreateReqJitBufMes(); } void CreateReqJitBufMes() { Protocol.CreateReqJitBufMes(); }
protected: protected:

View file

@ -46,7 +46,8 @@ MESSAGES
+--------------------------+ +--------------------------+
- Request jitter buffer size: PROTMESSID_REQ_JITT_BUF_SIZE - Request jitter buffer size: PROTMESSID_REQ_JITT_BUF_SIZE
no data
note: does not have any data -> n = 0
@ -95,8 +96,12 @@ void CProtocol::EnqueueMessage ( CVector<uint8_t>& vecMessage,
// create send message object for the queue // create send message object for the queue
CSendMessage SendMessageObj ( vecMessage, iCnt, iID ); CSendMessage SendMessageObj ( vecMessage, iCnt, iID );
Mutex.lock();
{
// we want to have a FIFO: we add at the end and take from the beginning // we want to have a FIFO: we add at the end and take from the beginning
SendMessQueue.push_back ( SendMessageObj ); SendMessQueue.push_back ( SendMessageObj );
}
Mutex.unlock();
// if list was empty, initiate send process // if list was empty, initiate send process
if ( bListWasEmpty ) if ( bListWasEmpty )
@ -107,12 +112,27 @@ void CProtocol::EnqueueMessage ( CVector<uint8_t>& vecMessage,
void CProtocol::SendMessage() void CProtocol::SendMessage()
{ {
CVector<uint8_t> vecMessage;
bool bSendMess = false;
Mutex.lock();
{
// we have to check that list is not empty, since in another thread the // we have to check that list is not empty, since in another thread the
// last element of the list might have been erased // last element of the list might have been erased
if ( !SendMessQueue.empty() ) if ( !SendMessQueue.empty() )
{
vecMessage.Init ( SendMessQueue.front().vecMessage.Size() );
vecMessage = SendMessQueue.front().vecMessage;
bSendMess = true;
}
}
Mutex.unlock();
if ( bSendMess )
{ {
// send message // send message
emit MessReadyForSending ( SendMessQueue.front().vecMessage ); emit MessReadyForSending ( vecMessage );
// start time-out timer if not active // start time-out timer if not active
if ( !TimerSendMess.isActive() ) if ( !TimerSendMess.isActive() )
@ -144,27 +164,11 @@ void CProtocol::CreateAndSendAcknMess ( const int& iID, const int& iCnt )
} }
void CProtocol::DeleteSendMessQueue() void CProtocol::DeleteSendMessQueue()
{
/*
Actually, this function must be secured by a mutex, too. The problem is that
this function is called from OnSendProtMessage in client which is called
from a mutexed function of this object. In this case, we will get a dead
lock.
*/
// delete complete "send message queue"
SendMessQueue.clear();
}
/*
The following functions are access functions from different threads. These
functions have to be secured by a mutex to avoid data corruption
*/
void CProtocol::OnTimerSendMess()
{ {
Mutex.lock(); Mutex.lock();
{ {
SendMessage(); // delete complete "send message queue"
SendMessQueue.clear();
} }
Mutex.unlock(); Mutex.unlock();
} }
@ -176,18 +180,16 @@ bool CProtocol::ParseMessage ( const CVector<unsigned char>& vecbyData,
return code: true -> ok; false -> error return code: true -> ok; false -> error
*/ */
bool bRet; bool bRet;
Mutex.lock();
{
int iRecCounter, iRecID, iData; int iRecCounter, iRecID, iData;
unsigned int iPos; unsigned int iPos;
CVector<uint8_t> vecData; CVector<uint8_t> vecData;
bool bSendNextMess;
// convert unsigned char in uint8_t, TODO convert all buffers in uint8_t // convert unsigned char in uint8_t, TODO convert all buffers in uint8_t
CVector<uint8_t> vecbyDataConv ( iNumBytes ); CVector<uint8_t> vecbyDataConv ( iNumBytes );
for ( int i = 0; i < iNumBytes; i++ ) { for ( int i = 0; i < iNumBytes; i++ ) {
vecbyDataConv[i] = static_cast<uint8_t> ( vecbyData[i] ); vecbyDataConv[i] = static_cast<uint8_t> ( vecbyData[i] );
} }
@ -218,6 +220,8 @@ for ( int i = 0; i < iNumBytes; i++ ) {
iPos = 0; iPos = 0;
iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) ); iData = static_cast<int> ( GetValFromStream ( vecData, iPos, 2 ) );
Mutex.lock();
{
// check if this is the correct acknowledgment // check if this is the correct acknowledgment
if ( ( SendMessQueue.front().iCnt == iRecCounter ) && if ( ( SendMessQueue.front().iCnt == iRecCounter ) &&
( SendMessQueue.front().iID == iData ) ) ( SendMessQueue.front().iID == iData ) )
@ -226,6 +230,17 @@ for ( int i = 0; i < iNumBytes; i++ ) {
SendMessQueue.pop_front(); SendMessQueue.pop_front();
// send next message in queue // send next message in queue
bSendNextMess = true;
}
else
{
bSendNextMess = false;
}
}
Mutex.unlock();
if ( bSendNextMess )
{
SendMessage(); SendMessage();
} }
@ -267,25 +282,26 @@ for ( int i = 0; i < iNumBytes; i++ ) {
{ {
bRet = false; // return error code bRet = false; // return error code
} }
}
Mutex.unlock();
return bRet; return bRet;
} }
void CProtocol::CreateJitBufMes ( const int iJitBufSize ) void CProtocol::CreateJitBufMes ( const int iJitBufSize )
{ {
Mutex.lock();
{
CVector<uint8_t> vecNewMessage; CVector<uint8_t> vecNewMessage;
CVector<uint8_t> vecData ( 2 ); // 2 bytes of data CVector<uint8_t> vecData ( 2 ); // 2 bytes of data
int iCurCounter;
unsigned int iPos = 0; // init position pointer unsigned int iPos = 0; // init position pointer
Mutex.lock();
{
// store current counter value // store current counter value
const int iCurCounter = iCounter; iCurCounter = iCounter;
// increase counter (wraps around automatically) // increase counter (wraps around automatically)
iCounter++; iCounter++;
}
Mutex.unlock();
// build data vector // build data vector
PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iJitBufSize ), 2 ); PutValOnStream ( vecData, iPos, static_cast<uint32_t> ( iJitBufSize ), 2 );
@ -295,29 +311,28 @@ void CProtocol::CreateJitBufMes ( const int iJitBufSize )
// enqueue message // enqueue message
EnqueueMessage ( vecNewMessage, iCurCounter, PROTMESSID_JITT_BUF_SIZE ); EnqueueMessage ( vecNewMessage, iCurCounter, PROTMESSID_JITT_BUF_SIZE );
}
Mutex.unlock();
} }
void CProtocol::CreateReqJitBufMes() void CProtocol::CreateReqJitBufMes()
{ {
CVector<uint8_t> vecNewMessage;
int iCurCounter;
Mutex.lock(); Mutex.lock();
{ {
CVector<uint8_t> vecNewMessage;
// store current counter value // store current counter value
const int iCurCounter = iCounter; iCurCounter = iCounter;
// increase counter (wraps around automatically) // increase counter (wraps around automatically)
iCounter++; iCounter++;
}
Mutex.unlock();
// build complete message // build complete message
GenMessageFrame ( vecNewMessage, iCurCounter, PROTMESSID_REQ_JITT_BUF_SIZE, CVector<uint8_t> ( 0 ) ); GenMessageFrame ( vecNewMessage, iCurCounter, PROTMESSID_REQ_JITT_BUF_SIZE, CVector<uint8_t> ( 0 ) );
// enqueue message // enqueue message
EnqueueMessage ( vecNewMessage, iCurCounter, PROTMESSID_REQ_JITT_BUF_SIZE ); EnqueueMessage ( vecNewMessage, iCurCounter, PROTMESSID_REQ_JITT_BUF_SIZE );
}
Mutex.unlock();
} }

View file

@ -117,15 +117,17 @@ protected:
void SendMessage(); void SendMessage();
uint8_t iCounter;
int iOldRecID, iOldRecCnt; int iOldRecID, iOldRecCnt;
// these two objects must be sequred by a mutex
uint8_t iCounter;
std::list<CSendMessage> SendMessQueue; std::list<CSendMessage> SendMessQueue;
QTimer TimerSendMess; QTimer TimerSendMess;
QMutex Mutex; QMutex Mutex;
public slots: public slots:
void OnTimerSendMess(); void OnTimerSendMess() { SendMessage(); }
signals: signals:
// transmitting // transmitting