i2pd/libi2pd/util.h

172 lines
3.4 KiB
C
Raw Normal View History

2014-01-30 07:28:07 +04:00
#ifndef UTIL_H
#define UTIL_H
#include <string>
2017-01-12 03:45:04 +03:00
#include <functional>
#include <memory>
2017-01-16 23:40:01 +03:00
#include <mutex>
2020-02-03 01:05:30 +03:00
#include <thread>
#include <utility>
2014-10-31 21:17:52 +03:00
#include <boost/asio.hpp>
#ifdef ANDROID
2018-12-27 03:16:38 +03:00
#ifndef __clang__
#include <boost/lexical_cast.hpp>
namespace std
{
2018-12-27 03:16:38 +03:00
template <typename T>
std::string to_string(T value)
{
return boost::lexical_cast<std::string>(value);
}
2016-10-26 23:19:32 +03:00
2018-12-27 03:16:38 +03:00
inline int stoi(const std::string& str)
{
return boost::lexical_cast<int>(str);
}
}
#endif
2018-12-27 03:16:38 +03:00
#endif
2014-01-30 07:28:07 +04:00
namespace i2p
{
namespace util
{
2017-01-11 00:14:18 +03:00
template<class T>
2017-01-11 00:14:18 +03:00
class MemoryPool
{
2017-11-01 04:25:52 +03:00
//BOOST_STATIC_ASSERT_MSG(sizeof(T) >= sizeof(void*), "size cannot be less that general pointer size");
2017-09-29 10:17:23 +03:00
2017-01-11 00:14:18 +03:00
public:
MemoryPool (): m_Head (nullptr) {}
2018-01-06 06:48:51 +03:00
~MemoryPool ()
{
while (m_Head)
2017-01-11 00:14:18 +03:00
{
auto tmp = m_Head;
m_Head = static_cast<T*>(*(void * *)m_Head); // next
2019-06-25 23:37:06 +03:00
::operator delete ((void *)tmp);
2017-01-11 00:14:18 +03:00
}
2018-01-06 06:48:51 +03:00
}
2017-01-11 00:14:18 +03:00
template<typename... TArgs>
2017-01-12 03:45:04 +03:00
T * Acquire (TArgs&&... args)
2017-01-11 00:14:18 +03:00
{
if (!m_Head) return new T(std::forward<TArgs>(args)...);
2017-01-11 00:14:18 +03:00
else
{
auto tmp = m_Head;
m_Head = static_cast<T*>(*(void * *)m_Head); // next
return new (tmp)T(std::forward<TArgs>(args)...);
2017-01-11 00:14:18 +03:00
}
}
void Release (T * t)
{
2017-01-11 05:31:52 +03:00
if (!t) return;
2017-01-11 00:14:18 +03:00
t->~T ();
2017-01-11 05:31:52 +03:00
*(void * *)t = m_Head; // next
2018-01-06 06:48:51 +03:00
m_Head = t;
2017-01-11 00:14:18 +03:00
}
2017-01-12 03:45:04 +03:00
template<typename... TArgs>
std::unique_ptr<T, std::function<void(T*)> > AcquireUnique (TArgs&&... args)
{
return std::unique_ptr<T, std::function<void(T*)> >(Acquire (std::forward<TArgs>(args)...),
2017-01-12 03:45:04 +03:00
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
}
2018-01-06 06:48:51 +03:00
2017-01-19 18:20:34 +03:00
template<typename... TArgs>
std::shared_ptr<T> AcquireShared (TArgs&&... args)
{
return std::shared_ptr<T>(Acquire (std::forward<TArgs>(args)...),
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
2017-01-19 18:20:34 +03:00
}
2017-01-16 23:40:01 +03:00
protected:
2017-01-11 00:14:18 +03:00
T * m_Head;
2018-01-06 06:48:51 +03:00
};
2017-01-11 00:14:18 +03:00
2017-01-16 23:40:01 +03:00
template<class T>
class MemoryPoolMt: public MemoryPool<T>
{
public:
MemoryPoolMt () {}
2017-01-16 23:40:01 +03:00
template<typename... TArgs>
T * AcquireMt (TArgs&&... args)
{
if (!this->m_Head) return new T(std::forward<TArgs>(args)...);
2017-01-16 23:40:01 +03:00
std::lock_guard<std::mutex> l(m_Mutex);
return this->Acquire (std::forward<TArgs>(args)...);
2017-01-16 23:40:01 +03:00
}
void ReleaseMt (T * t)
{
std::lock_guard<std::mutex> l(m_Mutex);
2018-01-06 06:48:51 +03:00
this->Release (t);
2017-01-16 23:40:01 +03:00
}
template<template<typename, typename...>class C, typename... R>
2018-01-06 06:48:51 +03:00
void ReleaseMt(const C<T *, R...>& c)
2017-01-16 23:40:01 +03:00
{
std::lock_guard<std::mutex> l(m_Mutex);
for (auto& it: c)
this->Release (it);
2018-01-06 06:48:51 +03:00
}
2017-01-16 23:40:01 +03:00
private:
2018-01-06 06:48:51 +03:00
2017-01-16 23:40:01 +03:00
std::mutex m_Mutex;
};
2020-02-03 01:05:30 +03:00
class RunnableService
{
public:
RunnableService (const std::string& name): m_Name (name), m_IsRunning (false) {}
virtual ~RunnableService () {}
boost::asio::io_service& GetService () { return m_Service; }
bool IsRunning () const { return m_IsRunning; };
void StartService ();
void StopService ();
private:
void Run ();
private:
std::string m_Name;
bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread;
boost::asio::io_service m_Service;
};
class RunnableServiceWithWork: public RunnableService
{
public:
RunnableServiceWithWork (const std::string& name):
RunnableService (name), m_Work (GetService ()) {}
private:
boost::asio::io_service::work m_Work;
};
2014-10-31 21:17:52 +03:00
namespace net
{
int GetMTU (const boost::asio::ip::address& localAddress);
2016-06-29 18:06:51 +03:00
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
2014-10-31 21:17:52 +03:00
}
2014-01-30 07:28:07 +04:00
}
}
#endif