lokinet/include/llarp/codel.hpp
despair86 bdc54835c2 initial windows server port. Requires Windows 2000 Server or later.
- updated CMake build script
- builds with Microsoft C++ 19.1x. such builds require Windows 8.1 or later
  unless you have the .NET Server 2003-toolset (v141_xp)
- windows port requires a C++17 compiler since cpp17::filesystem is POSIX-only
- HAVE_CXX17_FILESYSTEM manual toggle in CMake. You must manually specify where
  std::[experimental::]filesystem is defined in LDFLAGS or CMAKE_x_LINKER_FLAGS.
- IPv6 support can be added at any time, and the windows sdk still has that
  inline getaddrinfo(3) if it can't find a suitable IPv6 stack.
- inline code for mingw-w64: there's a few bits and pieces still missing simply because
  mingw-w64 derives its windows sdk from wine and reactos, and then writing all the newer
  stuff into it by hand straight from the MSDN manpages.
- misc. C++11 stuff (nullptr and friends)
- Internal file handling code takes UTF-8 or plain 8-bit text, NTFS is UTF-16, so
  std::filesystem::path::c_str() is wchar_t. That's no good unless you first
  call std::filesystem::path::string().
- implemented getifaddrs(3) and if_nametoindex(3) on top of GetAdapters[Info|Addresses](2).
- updated readme with new info

BONUS: may implement Solaris/illumos IOCP someday...

-despair86
2018-08-01 23:41:02 -05:00

134 lines
3.3 KiB
C++

#ifndef LLARP_CODEL_QUEUE_HPP
#define LLARP_CODEL_QUEUE_HPP
#ifdef _MSC_VER
#define NOMINMAX
#endif
#include <llarp/time.h>
#include <llarp/logger.hpp>
#include <llarp/threading.hpp>
#include <algorithm>
#include <cmath>
#include <functional>
#include <queue>
#include <string>
namespace llarp
{
namespace util
{
struct DummyMutex
{
};
struct DummyLock
{
DummyLock(const DummyMutex& mtx){};
~DummyLock()
{
}
};
template < typename T, typename GetTime >
struct CoDelCompareTime
{
bool
operator()(const T& left, const T& right) const
{
return GetTime()(left) < GetTime()(right);
}
};
template < typename T >
struct CoDelComparePriority
{
bool
operator()(const T& left, const T& right) const
{
return left < right;
}
};
template < typename T, typename GetTime, typename PutTime, typename Compare,
typename Mutex_t = std::mutex,
typename Lock_t = std::lock_guard< std::mutex >,
llarp_time_t dropMs = 5, llarp_time_t initialIntervalMs = 100 >
struct CoDelQueue
{
CoDelQueue(const std::string& name) : m_name(name)
{
}
size_t
Size()
{
Lock_t lock(m_QueueMutex);
return m_Queue.size();
}
void
Put(T i)
{
Lock_t lock(m_QueueMutex);
// llarp::LogInfo("CoDelQueue::Put - adding item, queue now has ",
// m_Queue.size(), " items at ", getTime(*item));
PutTime()(i);
m_Queue.push(i);
if(firstPut == 0)
firstPut = GetTime()(i);
}
template < typename Queue_t >
void
Process(Queue_t& result)
{
llarp_time_t lowest = 0xFFFFFFFFFFFFFFFFUL;
// auto start = llarp_time_now_ms();
// llarp::LogInfo("CoDelQueue::Process - start at ", start);
Lock_t lock(m_QueueMutex);
auto start = firstPut;
while(m_Queue.size())
{
// llarp::LogInfo("CoDelQueue::Process - queue has ", m_Queue.size());
const auto& item = m_Queue.top();
auto dlt = start - GetTime()(item);
// llarp::LogInfo("CoDelQueue::Process - dlt ", dlt);
lowest = std::min(dlt, lowest);
if(m_Queue.size() == 1)
{
// llarp::LogInfo("CoDelQueue::Process - single item: lowest ",
// lowest, " dropMs: ", dropMs);
if(lowest > dropMs)
{
// drop
nextTickInterval += initialIntervalMs / std::sqrt(++dropNum);
delete item;
m_Queue.pop();
break;
}
else
{
nextTickInterval = initialIntervalMs;
dropNum = 0;
}
}
// llarp::LogInfo("CoDelQueue::Process - passing");
result.push(item);
m_Queue.pop();
}
firstPut = 0;
}
llarp_time_t firstPut = 0;
size_t dropNum = 0;
llarp_time_t nextTickInterval = initialIntervalMs;
Mutex_t m_QueueMutex;
std::priority_queue< T, std::vector< T >, Compare > m_Queue;
std::string m_name;
};
} // namespace util
} // namespace llarp
#endif