Пример #1
0
void CRateLimiter::OnTimer(wxTimerEvent& event)
{
	std::list<CRateLimiterObject*> objectsToUnwait;
	for (int i = 0; i < 2; i++)
	{
		m_tokenDebt[i] = 0;

		if (!m_objectList.size())
			continue;

		int limit = m_pOptions->GetOptionVal(OPTION_SPEEDLIMIT_INBOUND + i) * 1024;
		if (!limit)
		{
			for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); iter++)
			{
				(*iter)->m_bytesAvailable[i] = -1;
				if ((*iter)->m_waiting[i])
					m_wakeupList[i].push_back(*iter);
			}
			continue;
		}

		int tokens = limit * tickDelay / 1000;
		if (!tokens)
			tokens = 1;
		int maxTokens = tokens * GetBucketSize();

		// Get amount of tokens for each object
		int tokensPerObject = tokens / m_objectList.size();
		
		if (!tokensPerObject)
			tokensPerObject = 1;
		tokens = 0;

		// This list will hold all objects which didn't reach maxTokens
		std::list<CRateLimiterObject*> unsaturatedObjects;

		for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); iter++)
		{
			if ((*iter)->m_bytesAvailable[i] == -1)
			{
				wxASSERT(!(*iter)->m_waiting[i]);
				(*iter)->m_bytesAvailable[i] = tokensPerObject;
				unsaturatedObjects.push_back(*iter);
			}
			else
			{
				(*iter)->m_bytesAvailable[i] += tokensPerObject;
				if ((*iter)->m_bytesAvailable[i] > maxTokens)
				{
					tokens += (*iter)->m_bytesAvailable[i] - maxTokens;
					(*iter)->m_bytesAvailable[i] = maxTokens;
				}
				else
					unsaturatedObjects.push_back(*iter);

				if ((*iter)->m_waiting[i])
					m_wakeupList[i].push_back(*iter);
			}
		}

		// If there are any left-over tokens (in case of objects with a rate below the limit)
		// assign to the unsaturated sources
		while (tokens && !unsaturatedObjects.empty())
		{
			tokensPerObject = tokens / unsaturatedObjects.size();
			if (!tokensPerObject)
				break;
			tokens = 0;

			std::list<CRateLimiterObject*> objects;
			objects.swap(unsaturatedObjects);

			for (std::list<CRateLimiterObject*>::iterator iter = objects.begin(); iter != objects.end(); iter++)
			{
				(*iter)->m_bytesAvailable[i] += tokensPerObject;
				if ((*iter)->m_bytesAvailable[i] > maxTokens)
				{
					tokens += (*iter)->m_bytesAvailable[i] - maxTokens;
					(*iter)->m_bytesAvailable[i] = maxTokens;
				}
				else
					unsaturatedObjects.push_back(*iter);
			}
		}
	}
	WakeupWaitingObjects();

	if (m_objectList.empty())
		m_timer.Stop();
}
Пример #2
0
void CRateLimiter::OnTimer(fz::timer_id)
{
	fz::scoped_lock lock(sync_);

	int64_t const limits[2] = { GetLimit(inbound), GetLimit(outbound) };

	for (int i = 0; i < 2; ++i) {
		m_tokenDebt[i] = 0;

		if (m_objectList.empty())
			continue;

		if (limits[i] == 0) {
			for (auto iter = m_objectList.begin(); iter != m_objectList.end(); ++iter) {
				(*iter)->m_bytesAvailable[i] = -1;
				if ((*iter)->m_waiting[i])
					m_wakeupList[i].push_back(*iter);
			}
			continue;
		}

		int64_t tokens = (limits[i] * tickDelay) / 1000;
		int64_t maxTokens = tokens * GetBucketSize();

		// Get amount of tokens for each object
		int64_t tokensPerObject = tokens / m_objectList.size();

		if (tokensPerObject == 0)
			tokensPerObject = 1;
		tokens = 0;

		// This list will hold all objects which didn't reach maxTokens
		std::list<CRateLimiterObject*> unsaturatedObjects;

		for (auto iter = m_objectList.begin(); iter != m_objectList.end(); ++iter) {
			if ((*iter)->m_bytesAvailable[i] == -1) {
				assert(!(*iter)->m_waiting[i]);
				(*iter)->m_bytesAvailable[i] = tokensPerObject;
				unsaturatedObjects.push_back(*iter);
			}
			else {
				(*iter)->m_bytesAvailable[i] += tokensPerObject;
				if ((*iter)->m_bytesAvailable[i] > maxTokens)
				{
					tokens += (*iter)->m_bytesAvailable[i] - maxTokens;
					(*iter)->m_bytesAvailable[i] = maxTokens;
				}
				else
					unsaturatedObjects.push_back(*iter);

				if ((*iter)->m_waiting[i])
					m_wakeupList[i].push_back(*iter);
			}
		}

		// If there are any left-over tokens (in case of objects with a rate below the limit)
		// assign to the unsaturated sources
		while (tokens != 0 && !unsaturatedObjects.empty()) {
			tokensPerObject = tokens / unsaturatedObjects.size();
			if (tokensPerObject == 0)
				break;
			tokens = 0;

			std::list<CRateLimiterObject*> objects;
			objects.swap(unsaturatedObjects);

			for (auto iter = objects.begin(); iter != objects.end(); ++iter) {
				(*iter)->m_bytesAvailable[i] += tokensPerObject;
				if ((*iter)->m_bytesAvailable[i] > maxTokens) {
					tokens += (*iter)->m_bytesAvailable[i] - maxTokens;
					(*iter)->m_bytesAvailable[i] = maxTokens;
				}
				else
					unsaturatedObjects.push_back(*iter);
			}
		}
	}

	WakeupWaitingObjects(lock);

	if (m_objectList.empty() || (limits[inbound] == 0 && limits[outbound] == 0)) {
		if (m_timer) {
			stop_timer(m_timer);
			m_timer = 0;
		}
	}
}
Пример #3
0
void CRateLimiter::OnTimer(wxTimerEvent& event)
{
	for (int i = 0; i < 2; ++i)
	{
		m_tokenDebt[i] = 0;

		if (m_objectList.empty())
			continue;

		wxLongLong limit = GetLimit((enum rate_direction)i);
		if (limit == 0)
		{
			for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); ++iter)
			{
				(*iter)->m_bytesAvailable[i] = -1;
				if ((*iter)->m_waiting[i])
					m_wakeupList[i].push_back(*iter);
			}
			continue;
		}

		wxLongLong tokens = (limit * tickDelay) / 1000;
		wxLongLong maxTokens = tokens * GetBucketSize();

		// Get amount of tokens for each object
		wxLongLong tokensPerObject = tokens / m_objectList.size();

		if (tokensPerObject == 0)
			tokensPerObject = 1;
		tokens = 0;

		// This list will hold all objects which didn't reach maxTokens
		std::list<CRateLimiterObject*> unsaturatedObjects;

		for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); ++iter)
		{
			if ((*iter)->m_bytesAvailable[i] == -1)
			{
				wxASSERT(!(*iter)->m_waiting[i]);
				(*iter)->m_bytesAvailable[i] = tokensPerObject;
				unsaturatedObjects.push_back(*iter);
			}
			else
			{
				(*iter)->m_bytesAvailable[i] += tokensPerObject;
				if ((*iter)->m_bytesAvailable[i] > maxTokens)
				{
					tokens += (*iter)->m_bytesAvailable[i] - maxTokens;
					(*iter)->m_bytesAvailable[i] = maxTokens;
				}
				else
					unsaturatedObjects.push_back(*iter);

				if ((*iter)->m_waiting[i])
					m_wakeupList[i].push_back(*iter);
			}
		}

		// If there are any left-over tokens (in case of objects with a rate below the limit)
		// assign to the unsaturated sources
		while (tokens != 0 && !unsaturatedObjects.empty())
		{
			tokensPerObject = tokens / unsaturatedObjects.size();
			if (tokensPerObject == 0)
				break;
			tokens = 0;

			std::list<CRateLimiterObject*> objects;
			objects.swap(unsaturatedObjects);

			for (std::list<CRateLimiterObject*>::iterator iter = objects.begin(); iter != objects.end(); ++iter)
			{
				(*iter)->m_bytesAvailable[i] += tokensPerObject;
				if ((*iter)->m_bytesAvailable[i] > maxTokens)
				{
					tokens += (*iter)->m_bytesAvailable[i] - maxTokens;
					(*iter)->m_bytesAvailable[i] = maxTokens;
				}
				else
					unsaturatedObjects.push_back(*iter);
			}
		}
	}
	WakeupWaitingObjects();

	if (m_objectList.empty())
		m_timer.Stop();
}