i2pd/libi2pd/util.h
Anatolii Cherednichenko 55534ea002 Reformat code
2022-08-30 02:11:28 +03:00

221 lines
6.1 KiB
C++

/*
* Copyright (c) 2013-2022, 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
*/
#ifndef UTIL_H
#define UTIL_H
#include <string>
#include <functional>
#include <memory>
#include <mutex>
#include <thread>
#include <utility>
#include <boost/asio.hpp>
#ifdef ANDROID
#ifndef __clang__
#include <boost/lexical_cast.hpp>
namespace std
{
template <typename T>
std::string to_string(T value)
{
return boost::lexical_cast<std::string>(value);
}
inline int stoi(const std::string& str)
{
return boost::lexical_cast<int>(str);
}
}
#endif
#endif
namespace i2p {
namespace util {
template<class T>
class MemoryPool {
//BOOST_STATIC_ASSERT_MSG(sizeof(T) >= sizeof(void*), "size cannot be less that general pointer size");
public:
MemoryPool() : m_Head(nullptr) {}
~MemoryPool() {
CleanUp();
}
void CleanUp() {
CleanUp(m_Head);
m_Head = nullptr;
}
template<typename... TArgs>
T *Acquire(TArgs &&... args) {
if (!m_Head) return new T(std::forward<TArgs>(args)...);
else {
auto tmp = m_Head;
m_Head = static_cast<T *>(*(void **) m_Head); // next
return new(tmp)T(std::forward<TArgs>(args)...);
}
}
void Release(T *t) {
if (!t) return;
t->~T();
*(void **) t = m_Head; // next
m_Head = t;
}
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)...),
std::bind(&MemoryPool<T>::Release, this, std::placeholders::_1));
}
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));
}
protected:
void CleanUp(T *head) {
while (head) {
auto tmp = head;
head = static_cast<T *>(*(void **) head); // next
::operator delete((void *) tmp);
}
}
protected:
T *m_Head;
};
template<class T>
class MemoryPoolMt : public MemoryPool<T> {
public:
MemoryPoolMt() {}
template<typename... TArgs>
T *AcquireMt(TArgs &&... args) {
if (!this->m_Head) return new T(std::forward<TArgs>(args)...);
std::lock_guard <std::mutex> l(m_Mutex);
return this->Acquire(std::forward<TArgs>(args)...);
}
void ReleaseMt(T *t) {
std::lock_guard <std::mutex> l(m_Mutex);
this->Release(t);
}
template<template<typename, typename...> class C, typename... R>
void ReleaseMt(const C<T *, R...> &c) {
std::lock_guard <std::mutex> l(m_Mutex);
for (auto &it: c)
this->Release(it);
}
template<typename... TArgs>
std::shared_ptr <T> AcquireSharedMt(TArgs &&... args) {
return std::shared_ptr<T>(AcquireMt(std::forward<TArgs>(args)...),
std::bind < void(MemoryPoolMt<T>::*)(T * ) >
(&MemoryPoolMt<T>::ReleaseMt, this, std::placeholders::_1));
}
void CleanUpMt() {
T *head;
{
std::lock_guard <std::mutex> l(m_Mutex);
head = this->m_Head;
this->m_Head = nullptr;
}
if (head) this->CleanUp(head);
}
private:
std::mutex m_Mutex;
};
class RunnableService {
protected:
RunnableService(const std::string &name) : m_Name(name), m_IsRunning(false) {}
virtual ~RunnableService() {}
boost::asio::io_service &GetIOService() { return m_Service; }
bool IsRunning() const { return m_IsRunning; };
void StartIOService();
void StopIOService();
private:
void Run();
private:
std::string m_Name;
volatile bool m_IsRunning;
std::unique_ptr <std::thread> m_Thread;
boost::asio::io_service m_Service;
};
class RunnableServiceWithWork : public RunnableService {
protected:
RunnableServiceWithWork(const std::string &name) :
RunnableService(name), m_Work(GetIOService()) {}
private:
boost::asio::io_service::work m_Work;
};
void SetThreadName(const char *name);
template<typename T>
class SaveStateHelper {
public:
SaveStateHelper(T &orig) : m_Original(orig), m_Copy(orig) {};
~SaveStateHelper() { m_Original = m_Copy; };
private:
T &m_Original;
T m_Copy;
};
namespace net {
int GetMTU(const boost::asio::ip::address &localAddress);
int GetMaxMTU(const boost::asio::ip::address_v6 &localAddress); // check tunnel broker for ipv6 address
const boost::asio::ip::address GetInterfaceAddress(const std::string &ifname, bool ipv6 = false);
boost::asio::ip::address_v6 GetYggdrasilAddress();
bool IsLocalAddress(const boost::asio::ip::address &addr);
bool IsInReservedRange(const boost::asio::ip::address &host);
bool IsYggdrasilAddress(const boost::asio::ip::address &addr);
}
}
}
#endif