[Windows Phone 7 Development and Hacking] Martin7Pro:
Template version

Using (simple example, the same way will be used between native threads and managed Silverlight UI):

#include "..\Templates\STQueue.h"

STQueue<tstring> qMessages(L"");

... // Called by [B]any thread[/B]:

void SafeMessage(tstring sMessage)
{
qMessages.push_front(sMessage);
PostMessage(hUnsafe, WM_FTP_MESSAGE, 0 , 0);
}
...

... // In UI thread:
LRESULT OnMsgMessage(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
bool bChange = false;
tstring szMessage = L"";
while ((szMessage = qMessages.pop_back()) != L"")
{
szMessages += szMessage;
szMessages += L"\r\n";
bChange = true;
}
if (bChange)
{
SetDlgItemText(hMainDlg, IDC_EDITMessage, szMessages.c_str());
}
return TRUE;
}
...

STQueue.h:

template <class _Type> class STQItem
{
public:
STQItem<_Type> * pNext;
STQItem<_Type> * pPrev;
_Type Value;
STQItem(_Type & rV, STQItem<_Type> * pN = NULL, STQItem<_Type> * pP = NULL);
};

template <class _Type> class STQueue
{
protected:
STQItem<_Type> * pFront;
STQItem<_Type> * pBack;
_Type EmptyValue;

public:
STQueue(_Type EmptyV);
~STQueue();
bool push_front(const _Type & rNewValue);
const _Type & pop_back();
bool empty();
};

template <class _Type> STQItem<_Type>::STQItem(_Type & rV, STQItem<_Type> * pN, STQItem<_Type> * pP)
{
Value = rV;
pNext = pN;
pPrev = pP;
}

template <class _Type> STQueue<_Type>::STQueue(_Type EmptyV)
{
EmptyValue = EmptyV;
STQItem<_Type> * EmtyItem = new STQItem<_Type>(EmptyValue);
pFront = EmtyItem;
pBack = EmtyItem;
}

template <class _Type> STQueue<_Type>::~STQueue()
{
while (pop_back() != EmptyValue)
{
}
delete pBack;
}

template <class _Type> bool STQueue<_Type>::push_front(const _Type & rNewValue)
{ // nonblocking push, but theoretically forever cycle is possible for low priority thread!
STQItem<_Type> * pNewFront = new STQItem<_Type>(EmptyValue);
if (pNewFront)
{
STQItem<_Type> * pProbablyFront;
InterlockedExchangePointer(&pProbablyFront, pFront);
pNewFront->pNext = pProbablyFront;
pNewFront->pPrev = NULL;
pNewFront->Value = rNewValue;
while (InterlockedCompareExchangePointer(&pFront, pNewFront, pProbablyFront) != pProbablyFront)
{ // Another writer changed front pointer, active writer must try it again.
InterlockedExchangePointer(&pProbablyFront, pFront);
pNewFront->pNext = pProbablyFront;
}
return true; // Success allways.
}
return false; // Insufficient memory.
}

template <class _Type> const _Type & STQueue<_Type>::pop_back()
{ // one reader allowed only!!!
STQItem<_Type> * pBackward;
InterlockedExchangePointer(&pBackward, pFront); // Safe copy of actual front pointer
if (pBackward == pBack) // Queue is empty in time of interlocked attempt.
{
return EmptyValue;
}
if (!pBack->pPrev)
{ //	If backward queue is not beginned, reconstruct it from safe front pointer.
while (pBackward != pBack && !pBackward->pNext->pPrev)
{
pBackward->pNext->pPrev = pBackward;
pBackward = pBackward->pNext;
}
}
//	One reader can safe read from back and manipulate with backward queue.
STQItem<_Type> * pDelete = pBack;
pBack->pPrev->pNext = NULL;
pBack = pBack->pPrev;
delete pDelete;
return pBack->Value;
/* // This is not necessary, but it is more clean:
void * pResult = pBack->pValue;
pBack->pValue = NULL;
return pResult;
*/
}

template <class _Type> bool STQueue<_Type>::empty()
{
if(last==NULL)
return TRUE;
else
return FALSE;
}