I'm assuming that application is running in multiple threads, and in single process:
Code:
/* global variables */
LONG volatile lAvailableBandwidth = 0; /* -1000000 = INFINITE */
HANDLE hSemaphore;
LONG volatile lThreadWaitCount = 0;
CRITICAL_SECTION csBandwidth;
/* send */
BOOL SendData(Socket, PCHAR pBuffer, LONG lSize)
{
WSABUF Buffer;
DWORD dwBytes;
BOOL bLoop;
bLoop = TRUE;
Buffer.buffer = pBuffer;
do {
if (lAvailableBandwidth == -1000000 ||
InterlockedDecrement(&lAvailableBandwidth) >= 0) {
Buffer.len = min(1024, lSize);
if (WSASend(Socket, &Buffer, 1, &dwBytes, 0, 0, 0) == SOCKET_ERROR) {
return FALSE;
}
Buffer.buf = &Buf.buffer[dwBytes];
lSize -= dwBytes;
} else {
EnterCriticalSection(&csBandwidth);
if (lAvailableBandwidth <= 0) {
lThreadWaitCount++;
LeaveCriticalSection(&csBandwidth);
if (WaitForSingleObject(hSemaphore, 2000) == WAIT_OBJECT_0) {
/* ???? */
return FALSE;
}
} else {
LeaveCriticalSection(&csBandwidth);
}
}
} while (lSize != 0);
return TRUE;
}
/* thread that manages throttling */
UINT WINAPI ThrottleThread(LPVOID lpNull)
{
LONG lReleaseCount = 0;
for (;bRunning;) {
EnterCriticalSection(&csBandwidth);
InterlockedExchange(&lAvailableBandwidth, 5000);
lReleaseCount = lThreadWaitCount;
lThreadWaitCount = 0;
LeaveCriticalSection(&csBandwidth);
if (lReleaseCount > 0) {
ReleaseSemaphore(hSemaphore, lReleaseCount, 0);
}
/* this could use multimediatimer for higher accuracy */
Sleep(1000);
}
}