2020-05-22 13:18:41 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
|
|
|
*
|
|
|
|
* This file is part of Purple i2pd project and licensed under BSD3
|
|
|
|
*
|
|
|
|
* See full license text in LICENSE file at top of project tree
|
|
|
|
*/
|
|
|
|
|
2014-01-30 03:28:07 +00:00
|
|
|
#ifndef UTIL_H
|
|
|
|
#define UTIL_H
|
|
|
|
|
|
|
|
#include <string>
|
2017-01-12 00:45:04 +00:00
|
|
|
#include <functional>
|
|
|
|
#include <memory>
|
2017-01-16 20:40:01 +00:00
|
|
|
#include <mutex>
|
2020-02-02 22:05:30 +00:00
|
|
|
#include <thread>
|
2017-09-28 21:03:07 +00:00
|
|
|
#include <utility>
|
2014-10-31 18:17:52 +00:00
|
|
|
#include <boost/asio.hpp>
|
2014-02-01 03:09:55 +00:00
|
|
|
|
2016-06-14 15:55:44 +00:00
|
|
|
#ifdef ANDROID
|
2018-12-27 00:16:38 +00:00
|
|
|
#ifndef __clang__
|
2016-10-26 00:00:00 +00:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2016-06-14 15:55:44 +00:00
|
|
|
namespace std
|
|
|
|
{
|
2018-12-27 00:16:38 +00:00
|
|
|
template <typename T>
|
|
|
|
std::string to_string(T value)
|
|
|
|
{
|
|
|
|
return boost::lexical_cast<std::string>(value);
|
|
|
|
}
|
2016-10-26 20:19:32 +00:00
|
|
|
|
2018-12-27 00:16:38 +00:00
|
|
|
inline int stoi(const std::string& str)
|
|
|
|
{
|
|
|
|
return boost::lexical_cast<int>(str);
|
|
|
|
}
|
2016-06-14 15:55:44 +00:00
|
|
|
}
|
|
|
|
#endif
|
2018-12-27 00:16:38 +00:00
|
|
|
#endif
|
2016-06-14 15:55:44 +00:00
|
|
|
|
2014-01-30 03:28:07 +00:00
|
|
|
namespace i2p
|
|
|
|
{
|
|
|
|
namespace util
|
|
|
|
{
|
2017-01-10 21:14:18 +00:00
|
|
|
|
2017-09-28 21:03:07 +00:00
|
|
|
template<class T>
|
2017-01-10 21:14:18 +00:00
|
|
|
class MemoryPool
|
|
|
|
{
|
2017-11-01 01:25:52 +00:00
|
|
|
//BOOST_STATIC_ASSERT_MSG(sizeof(T) >= sizeof(void*), "size cannot be less that general pointer size");
|
2017-09-29 07:17:23 +00:00
|
|
|
|
2017-01-10 21:14:18 +00:00
|
|
|
public:
|
|
|
|
|
2017-09-28 21:03:07 +00:00
|
|
|
MemoryPool (): m_Head (nullptr) {}
|
2018-01-06 03:48:51 +00:00
|
|
|
~MemoryPool ()
|
|
|
|
{
|
|
|
|
while (m_Head)
|
2017-01-10 21:14:18 +00:00
|
|
|
{
|
|
|
|
auto tmp = m_Head;
|
|
|
|
m_Head = static_cast<T*>(*(void * *)m_Head); // next
|
2019-06-25 20:37:06 +00:00
|
|
|
::operator delete ((void *)tmp);
|
2017-01-10 21:14:18 +00:00
|
|
|
}
|
2018-01-06 03:48:51 +00:00
|
|
|
}
|
2017-01-10 21:14:18 +00:00
|
|
|
|
|
|
|
template<typename... TArgs>
|
2017-01-12 00:45:04 +00:00
|
|
|
T * Acquire (TArgs&&... args)
|
2017-01-10 21:14:18 +00:00
|
|
|
{
|
2017-09-28 21:03:07 +00:00
|
|
|
if (!m_Head) return new T(std::forward<TArgs>(args)...);
|
2017-01-10 21:14:18 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
auto tmp = m_Head;
|
|
|
|
m_Head = static_cast<T*>(*(void * *)m_Head); // next
|
2017-09-28 21:03:07 +00:00
|
|
|
return new (tmp)T(std::forward<TArgs>(args)...);
|
2017-01-10 21:14:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Release (T * t)
|
|
|
|
{
|
2017-01-11 02:31:52 +00:00
|
|
|
if (!t) return;
|
2017-01-10 21:14:18 +00:00
|
|
|
t->~T ();
|
2017-01-11 02:31:52 +00:00
|
|
|
*(void * *)t = m_Head; // next
|
2018-01-06 03:48:51 +00:00
|
|
|
m_Head = t;
|
2017-01-10 21:14:18 +00:00
|
|
|
}
|
|
|
|
|
2017-01-12 00:45:04 +00:00
|
|
|
template<typename... TArgs>
|
|
|
|
std::unique_ptr<T, std::function<void(T*)> > AcquireUnique (TArgs&&... args)
|
|
|
|
{
|
2017-09-28 21:03:07 +00:00
|
|
|
return std::unique_ptr<T, std::function<void(T*)> >(Acquire (std::forward<TArgs>(args)...),
|
2017-01-12 00:45:04 +00:00
|
|
|
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
|
|
|
|
}
|
2018-01-06 03:48:51 +00:00
|
|
|
|
2017-01-19 15:20:34 +00:00
|
|
|
template<typename... TArgs>
|
|
|
|
std::shared_ptr<T> AcquireShared (TArgs&&... args)
|
|
|
|
{
|
2017-09-28 21:03:07 +00:00
|
|
|
return std::shared_ptr<T>(Acquire (std::forward<TArgs>(args)...),
|
|
|
|
std::bind (&MemoryPool<T>::Release, this, std::placeholders::_1));
|
2017-01-19 15:20:34 +00:00
|
|
|
}
|
|
|
|
|
2017-01-16 20:40:01 +00:00
|
|
|
protected:
|
2017-01-10 21:14:18 +00:00
|
|
|
|
|
|
|
T * m_Head;
|
2018-01-06 03:48:51 +00:00
|
|
|
};
|
2017-01-10 21:14:18 +00:00
|
|
|
|
2017-01-16 20:40:01 +00:00
|
|
|
template<class T>
|
|
|
|
class MemoryPoolMt: public MemoryPool<T>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
2017-09-28 21:03:07 +00:00
|
|
|
MemoryPoolMt () {}
|
2017-01-16 20:40:01 +00:00
|
|
|
template<typename... TArgs>
|
|
|
|
T * AcquireMt (TArgs&&... args)
|
|
|
|
{
|
2017-09-28 21:03:07 +00:00
|
|
|
if (!this->m_Head) return new T(std::forward<TArgs>(args)...);
|
2017-01-16 20:40:01 +00:00
|
|
|
std::lock_guard<std::mutex> l(m_Mutex);
|
2017-09-28 21:03:07 +00:00
|
|
|
return this->Acquire (std::forward<TArgs>(args)...);
|
2017-01-16 20:40:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ReleaseMt (T * t)
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> l(m_Mutex);
|
2018-01-06 03:48:51 +00:00
|
|
|
this->Release (t);
|
2017-01-16 20:40:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<template<typename, typename...>class C, typename... R>
|
2018-01-06 03:48:51 +00:00
|
|
|
void ReleaseMt(const C<T *, R...>& c)
|
2017-01-16 20:40:01 +00:00
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> l(m_Mutex);
|
|
|
|
for (auto& it: c)
|
|
|
|
this->Release (it);
|
2018-01-06 03:48:51 +00:00
|
|
|
}
|
2017-01-16 20:40:01 +00:00
|
|
|
|
|
|
|
private:
|
2018-01-06 03:48:51 +00:00
|
|
|
|
2017-01-16 20:40:01 +00:00
|
|
|
std::mutex m_Mutex;
|
|
|
|
};
|
|
|
|
|
2020-02-02 22:05:30 +00:00
|
|
|
class RunnableService
|
|
|
|
{
|
2020-02-04 16:48:56 +00:00
|
|
|
protected:
|
2020-02-02 22:05:30 +00:00
|
|
|
|
|
|
|
RunnableService (const std::string& name): m_Name (name), m_IsRunning (false) {}
|
|
|
|
virtual ~RunnableService () {}
|
|
|
|
|
2020-02-04 16:48:56 +00:00
|
|
|
boost::asio::io_service& GetIOService () { return m_Service; }
|
2020-02-02 22:05:30 +00:00
|
|
|
bool IsRunning () const { return m_IsRunning; };
|
2020-03-01 10:25:50 +00:00
|
|
|
|
2020-02-04 16:48:56 +00:00
|
|
|
void StartIOService ();
|
|
|
|
void StopIOService ();
|
2020-02-02 22:05:30 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
void Run ();
|
2020-03-01 10:25:50 +00:00
|
|
|
|
2020-02-02 22:05:30 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
std::string m_Name;
|
2020-02-02 23:58:58 +00:00
|
|
|
volatile bool m_IsRunning;
|
2020-02-02 22:05:30 +00:00
|
|
|
std::unique_ptr<std::thread> m_Thread;
|
|
|
|
boost::asio::io_service m_Service;
|
2020-03-01 10:25:50 +00:00
|
|
|
};
|
2020-02-02 22:05:30 +00:00
|
|
|
|
|
|
|
class RunnableServiceWithWork: public RunnableService
|
|
|
|
{
|
2020-02-04 16:48:56 +00:00
|
|
|
protected:
|
2020-02-02 22:05:30 +00:00
|
|
|
|
2020-03-01 10:25:50 +00:00
|
|
|
RunnableServiceWithWork (const std::string& name):
|
|
|
|
RunnableService (name), m_Work (GetIOService ()) {}
|
|
|
|
|
2020-02-02 22:05:30 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
boost::asio::io_service::work m_Work;
|
2020-03-01 10:25:50 +00:00
|
|
|
};
|
|
|
|
|
2020-12-07 03:22:16 +00:00
|
|
|
void SetThreadName (const char *name);
|
|
|
|
|
2020-12-27 16:18:53 +00:00
|
|
|
template<typename T>
|
|
|
|
class SaveStateHelper
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
SaveStateHelper (T& orig): m_Original (orig), m_Copy (orig) {};
|
|
|
|
~SaveStateHelper () { m_Original = m_Copy; };
|
2021-05-30 00:23:00 +00:00
|
|
|
|
2020-12-27 16:18:53 +00:00
|
|
|
private:
|
|
|
|
|
|
|
|
T& m_Original;
|
|
|
|
T m_Copy;
|
2021-05-30 00:23:00 +00:00
|
|
|
};
|
|
|
|
|
2014-10-31 18:17:52 +00:00
|
|
|
namespace net
|
|
|
|
{
|
|
|
|
int GetMTU (const boost::asio::ip::address& localAddress);
|
2020-12-07 03:22:16 +00:00
|
|
|
const boost::asio::ip::address GetInterfaceAddress (const std::string & ifname, bool ipv6=false);
|
2021-01-25 00:42:44 +00:00
|
|
|
boost::asio::ip::address_v6 GetYggdrasilAddress ();
|
2021-02-03 00:29:13 +00:00
|
|
|
bool IsLocalAddress (const boost::asio::ip::address& addr);
|
2021-02-01 23:00:03 +00:00
|
|
|
bool IsInReservedRange (const boost::asio::ip::address& host);
|
2021-01-29 18:27:49 +00:00
|
|
|
bool IsYggdrasilAddress (const boost::asio::ip::address& addr);
|
2014-10-31 18:17:52 +00:00
|
|
|
}
|
2014-01-30 03:28:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|