Thread: Throttling
View Single Post
Old 09-03-2004, 03:15 AM  
darkone
Disabled
 
darkone's Avatar
 
Join Date: Dec 2001
Posts: 2,230
Default

Ay, it's sometimes hard to understand what I'm saying. Here's old send routine:

Code:
BOOL SendOverlapped(LPIOSOCKET lpSocket, LPSOCKETOVERLAPPED lpOverlapped)
{
	LPIODEVICE	lpDevice;
	LPBANDWIDTH	lpBandwidth;
	DWORD		dwBytesSent, dwToSend, n;

	if (dwSchedulerUpdateSpeed &&
		(lpDevice = lpSocket->lpDevice) &&	
		(lpDevice->Outbound.bGlobalBandwidthLimit || lpSocket->Options.dwSendLimit))
	{
		lpBandwidth	= &lpDevice->Outbound;
		dwToSend	= 1024;
		//	Calculate maximum send amount
		for (n = 0;n < lpOverlapped->dwBuffers;n++)
		{
			if (lpOverlapped->Buffer[n].len > dwToSend)
			{
				lpOverlapped->Buffer[n].len	= dwToSend;
				lpOverlapped->dwBuffers	= n + 1;
				break;
			}
			else dwToSend	-= lpOverlapped->Buffer[n].len;
		}

		while (InterlockedExchange(&lpBandwidth->lLock, TRUE)) SwitchToThread();
		//	Check available bandwidth on device
		if (! lpBandwidth->dwGlobalBandwidthLeft)
		{
			//	Push item to queue
			if (! lpBandwidth->lpIOQueue[0][HEAD])
			{
				lpBandwidth->lpIOQueue[0][HEAD]	= lpOverlapped;
			}
			else lpBandwidth->lpIOQueue[0][TAIL]->lpNext	= lpOverlapped;
			lpBandwidth->lpIOQueue[0][TAIL]	= lpOverlapped;
			lpBandwidth->dwIOQueue[0]++;
			InterlockedExchange(&lpBandwidth->lLock, FALSE);
			return -1;
		}
#ifdef _REGISTERED
		//	Check available bandwidth for user
		if (lpSocket->Options.dwSendLimit &&
			! lpSocket->dwBandwidthLimit[0]--)
		{
			if (! lpBandwidth->lpIOQueue[1][HEAD])
			{
				lpBandwidth->lpIOQueue[1][HEAD]	= lpOverlapped;
			}
			else lpBandwidth->lpIOQueue[1][TAIL]->lpNext	= lpOverlapped;
			lpBandwidth->lpIOQueue[1][TAIL]	= lpOverlapped;
			lpBandwidth->dwIOQueue[1]++;
			lpSocket->dwBandwidthLimit[0]	= lpSocket->Options.dwSendLimit - 1;
			InterlockedExchange(&lpBandwidth->lLock, FALSE);
			return -1;
		}
#endif
		lpBandwidth->dwGlobalBandwidthLeft--;
		InterlockedExchange(&lpBandwidth->lLock, FALSE);
	}
	//	Send data
	if (WSASend(lpSocket->Socket, lpOverlapped->Buffer, lpOverlapped->dwBuffers,
		&dwBytesSent, 0, (LPWSAOVERLAPPED)lpOverlapped, NULL) == SOCKET_ERROR &&
		WSAGetLastError() != WSA_IO_PENDING) return -2;
	return -1;
}
As you can notice it throws request to queue, if bandwidth counter hits zero. Queued items are released by dedicated thread every few hundred milliseconds.
darkone is offline