first
This commit is contained in:
parent
4dddf79158
commit
8082b9b003
31
ipc.sln
Normal file
31
ipc.sln
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.32002.261
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ipc", "ipc\ipc.vcxproj", "{439884C2-9C07-434F-8B84-B51378F4A83E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{439884C2-9C07-434F-8B84-B51378F4A83E}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {E136A803-5D70-4B88-B6DD-063E35B4710E}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
68
ipc/3rdparty/include/libipc/buffer.h
vendored
Normal file
68
ipc/3rdparty/include/libipc/buffer.h
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
#include "libipc/def.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
|
||||||
|
class IPC_EXPORT buffer {
|
||||||
|
public:
|
||||||
|
using destructor_t = void (*)(void*, std::size_t);
|
||||||
|
|
||||||
|
buffer();
|
||||||
|
|
||||||
|
buffer(void* p, std::size_t s, destructor_t d);
|
||||||
|
buffer(void* p, std::size_t s, destructor_t d, void* additional);
|
||||||
|
buffer(void* p, std::size_t s);
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
explicit buffer(byte_t const (& data)[N])
|
||||||
|
: buffer(data, sizeof(data)) {
|
||||||
|
}
|
||||||
|
explicit buffer(char const & c);
|
||||||
|
|
||||||
|
buffer(buffer&& rhs);
|
||||||
|
~buffer();
|
||||||
|
|
||||||
|
void swap(buffer& rhs);
|
||||||
|
buffer& operator=(buffer rhs);
|
||||||
|
|
||||||
|
bool empty() const noexcept;
|
||||||
|
|
||||||
|
void * data() noexcept;
|
||||||
|
void const * data() const noexcept;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T get() const { return T(data()); }
|
||||||
|
|
||||||
|
std::size_t size() const noexcept;
|
||||||
|
|
||||||
|
std::tuple<void*, std::size_t> to_tuple() {
|
||||||
|
return std::make_tuple(data(), size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<void const *, std::size_t> to_tuple() const {
|
||||||
|
return std::make_tuple(data(), size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<byte_t> to_vector() const {
|
||||||
|
return {
|
||||||
|
get<byte_t const *>(),
|
||||||
|
get<byte_t const *>() + size()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
friend IPC_EXPORT bool operator==(buffer const & b1, buffer const & b2);
|
||||||
|
friend IPC_EXPORT bool operator!=(buffer const & b1, buffer const & b2);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class buffer_;
|
||||||
|
buffer_* p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ipc
|
39
ipc/3rdparty/include/libipc/condition.h
vendored
Normal file
39
ipc/3rdparty/include/libipc/condition.h
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // std::uint64_t
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
#include "libipc/def.h"
|
||||||
|
#include "libipc/mutex.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
namespace sync {
|
||||||
|
|
||||||
|
class IPC_EXPORT condition {
|
||||||
|
condition(condition const &) = delete;
|
||||||
|
condition &operator=(condition const &) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
condition();
|
||||||
|
explicit condition(char const *name);
|
||||||
|
~condition();
|
||||||
|
|
||||||
|
void const *native() const noexcept;
|
||||||
|
void *native() noexcept;
|
||||||
|
|
||||||
|
bool valid() const noexcept;
|
||||||
|
|
||||||
|
bool open(char const *name) noexcept;
|
||||||
|
void close() noexcept;
|
||||||
|
|
||||||
|
bool wait(ipc::sync::mutex &mtx, std::uint64_t tm = ipc::invalid_value) noexcept;
|
||||||
|
bool notify() noexcept;
|
||||||
|
bool broadcast() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class condition_;
|
||||||
|
condition_* p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sync
|
||||||
|
} // namespace ipc
|
68
ipc/3rdparty/include/libipc/def.h
vendored
Normal file
68
ipc/3rdparty/include/libipc/def.h
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits> // std::numeric_limits
|
||||||
|
#include <new>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
using byte_t = std::uint8_t;
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
struct uint;
|
||||||
|
|
||||||
|
template <> struct uint<8 > { using type = std::uint8_t ; };
|
||||||
|
template <> struct uint<16> { using type = std::uint16_t; };
|
||||||
|
template <> struct uint<32> { using type = std::uint32_t; };
|
||||||
|
template <> struct uint<64> { using type = std::uint64_t; };
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
using uint_t = typename uint<N>::type;
|
||||||
|
|
||||||
|
// constants
|
||||||
|
|
||||||
|
enum : std::uint32_t {
|
||||||
|
invalid_value = (std::numeric_limits<std::uint32_t>::max)(),
|
||||||
|
default_timeout = 100, // ms
|
||||||
|
};
|
||||||
|
|
||||||
|
enum : std::size_t {
|
||||||
|
data_length = 64,
|
||||||
|
large_msg_limit = data_length,
|
||||||
|
large_msg_align = 1024,
|
||||||
|
large_msg_cache = 32,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class relat { // multiplicity of the relationship
|
||||||
|
single,
|
||||||
|
multi
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class trans { // transmission
|
||||||
|
unicast,
|
||||||
|
broadcast
|
||||||
|
};
|
||||||
|
|
||||||
|
// producer-consumer policy flag
|
||||||
|
|
||||||
|
template <relat Rp, relat Rc, trans Ts>
|
||||||
|
struct wr {};
|
||||||
|
|
||||||
|
template <typename WR>
|
||||||
|
struct relat_trait;
|
||||||
|
|
||||||
|
template <relat Rp, relat Rc, trans Ts>
|
||||||
|
struct relat_trait<wr<Rp, Rc, Ts>> {
|
||||||
|
constexpr static bool is_multi_producer = (Rp == relat::multi);
|
||||||
|
constexpr static bool is_multi_consumer = (Rc == relat::multi);
|
||||||
|
constexpr static bool is_broadcast = (Ts == trans::broadcast);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename> class Policy, typename Flag>
|
||||||
|
struct relat_trait<Policy<Flag>> : relat_trait<Flag> {};
|
||||||
|
|
||||||
|
} // namespace ipc
|
54
ipc/3rdparty/include/libipc/export.h
vendored
Normal file
54
ipc/3rdparty/include/libipc/export.h
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
||||||
|
|
||||||
|
# define IPC_DECL_EXPORT Q_DECL_EXPORT
|
||||||
|
# define IPC_DECL_IMPORT Q_DECL_IMPORT
|
||||||
|
|
||||||
|
#else // defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compiler & system detection for IPC_DECL_EXPORT & IPC_DECL_IMPORT.
|
||||||
|
* Not using QtCore cause it shouldn't depend on Qt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# define IPC_DECL_EXPORT __declspec(dllexport)
|
||||||
|
# define IPC_DECL_IMPORT __declspec(dllimport)
|
||||||
|
#elif defined(__ARMCC__) || defined(__CC_ARM)
|
||||||
|
# if defined(ANDROID) || defined(__linux__) || defined(__linux)
|
||||||
|
# define IPC_DECL_EXPORT __attribute__((visibility("default")))
|
||||||
|
# define IPC_DECL_IMPORT __attribute__((visibility("default")))
|
||||||
|
# else
|
||||||
|
# define IPC_DECL_EXPORT __declspec(dllexport)
|
||||||
|
# define IPC_DECL_IMPORT __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
|
||||||
|
defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
|
||||||
|
# define IPC_DECL_EXPORT __declspec(dllexport)
|
||||||
|
# define IPC_DECL_IMPORT __declspec(dllimport)
|
||||||
|
# else
|
||||||
|
# define IPC_DECL_EXPORT __attribute__((visibility("default")))
|
||||||
|
# define IPC_DECL_IMPORT __attribute__((visibility("default")))
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define IPC_DECL_EXPORT __attribute__((visibility("default")))
|
||||||
|
# define IPC_DECL_IMPORT __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(Q_DECL_EXPORT) && defined(Q_DECL_IMPORT)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define IPC_EXPORT for exporting function & class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IPC_EXPORT
|
||||||
|
#if defined(LIBIPC_LIBRARY_SHARED_BUILDING__)
|
||||||
|
# define IPC_EXPORT IPC_DECL_EXPORT
|
||||||
|
#elif defined(LIBIPC_LIBRARY_SHARED_USING__)
|
||||||
|
# define IPC_EXPORT IPC_DECL_IMPORT
|
||||||
|
#else
|
||||||
|
# define IPC_EXPORT
|
||||||
|
#endif
|
||||||
|
#endif /*IPC_EXPORT*/
|
192
ipc/3rdparty/include/libipc/ipc.h
vendored
Normal file
192
ipc/3rdparty/include/libipc/ipc.h
vendored
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
#include "libipc/def.h"
|
||||||
|
#include "libipc/buffer.h"
|
||||||
|
#include "libipc/shm.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
|
||||||
|
using handle_t = void*;
|
||||||
|
using buff_t = buffer;
|
||||||
|
|
||||||
|
enum : unsigned {
|
||||||
|
sender,
|
||||||
|
receiver
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Flag>
|
||||||
|
struct IPC_EXPORT chan_impl {
|
||||||
|
static bool connect (ipc::handle_t * ph, char const * name, unsigned mode);
|
||||||
|
static bool reconnect (ipc::handle_t * ph, unsigned mode);
|
||||||
|
static void disconnect(ipc::handle_t h);
|
||||||
|
static void destroy (ipc::handle_t h);
|
||||||
|
|
||||||
|
static char const * name(ipc::handle_t h);
|
||||||
|
|
||||||
|
static std::size_t recv_count(ipc::handle_t h);
|
||||||
|
static bool wait_for_recv(ipc::handle_t h, std::size_t r_count, std::uint64_t tm);
|
||||||
|
|
||||||
|
static bool send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm);
|
||||||
|
static buff_t recv(ipc::handle_t h, std::uint64_t tm);
|
||||||
|
|
||||||
|
static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm);
|
||||||
|
static buff_t try_recv(ipc::handle_t h);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Flag>
|
||||||
|
class chan_wrapper {
|
||||||
|
private:
|
||||||
|
using detail_t = chan_impl<Flag>;
|
||||||
|
|
||||||
|
ipc::handle_t h_ = nullptr;
|
||||||
|
unsigned mode_ = ipc::sender;
|
||||||
|
bool connected_ = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
chan_wrapper() noexcept = default;
|
||||||
|
|
||||||
|
explicit chan_wrapper(char const * name, unsigned mode = ipc::sender)
|
||||||
|
: connected_{this->connect(name, mode)} {
|
||||||
|
}
|
||||||
|
|
||||||
|
chan_wrapper(chan_wrapper&& rhs) noexcept
|
||||||
|
: chan_wrapper{} {
|
||||||
|
swap(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
~chan_wrapper() {
|
||||||
|
detail_t::destroy(h_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(chan_wrapper& rhs) noexcept {
|
||||||
|
std::swap(h_ , rhs.h_);
|
||||||
|
std::swap(mode_ , rhs.mode_);
|
||||||
|
std::swap(connected_, rhs.connected_);
|
||||||
|
}
|
||||||
|
|
||||||
|
chan_wrapper& operator=(chan_wrapper rhs) noexcept {
|
||||||
|
swap(rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const * name() const noexcept {
|
||||||
|
return detail_t::name(h_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ipc::handle_t handle() const noexcept {
|
||||||
|
return h_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const noexcept {
|
||||||
|
return (handle() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned mode() const noexcept {
|
||||||
|
return mode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
chan_wrapper clone() const {
|
||||||
|
return chan_wrapper { name(), mode_ };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Building handle, then try connecting with name & mode flags.
|
||||||
|
*/
|
||||||
|
bool connect(char const * name, unsigned mode = ipc::sender | ipc::receiver) {
|
||||||
|
if (name == nullptr || name[0] == '\0') return false;
|
||||||
|
detail_t::disconnect(h_); // clear old connection
|
||||||
|
return connected_ = detail_t::connect(&h_, name, mode_ = mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try connecting with new mode flags.
|
||||||
|
*/
|
||||||
|
bool reconnect(unsigned mode) {
|
||||||
|
if (!valid()) return false;
|
||||||
|
if (connected_ && (mode_ == mode)) return true;
|
||||||
|
return connected_ = detail_t::reconnect(&h_, mode_ = mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void disconnect() {
|
||||||
|
if (!valid()) return;
|
||||||
|
detail_t::disconnect(h_);
|
||||||
|
connected_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t recv_count() const {
|
||||||
|
return detail_t::recv_count(h_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wait_for_recv(std::size_t r_count, std::uint64_t tm = invalid_value) const {
|
||||||
|
return detail_t::wait_for_recv(h_, r_count, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wait_for_recv(char const * name, std::size_t r_count, std::uint64_t tm = invalid_value) {
|
||||||
|
return chan_wrapper(name).wait_for_recv(r_count, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If timeout, this function would call 'force_push' to send the data forcibly.
|
||||||
|
*/
|
||||||
|
bool send(void const * data, std::size_t size, std::uint64_t tm = default_timeout) {
|
||||||
|
return detail_t::send(h_, data, size, tm);
|
||||||
|
}
|
||||||
|
bool send(buff_t const & buff, std::uint64_t tm = default_timeout) {
|
||||||
|
return this->send(buff.data(), buff.size(), tm);
|
||||||
|
}
|
||||||
|
bool send(std::string const & str, std::uint64_t tm = default_timeout) {
|
||||||
|
return this->send(str.c_str(), str.size() + 1, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If timeout, this function would just return false.
|
||||||
|
*/
|
||||||
|
bool try_send(void const * data, std::size_t size, std::uint64_t tm = default_timeout) {
|
||||||
|
return detail_t::try_send(h_, data, size, tm);
|
||||||
|
}
|
||||||
|
bool try_send(buff_t const & buff, std::uint64_t tm = default_timeout) {
|
||||||
|
return this->try_send(buff.data(), buff.size(), tm);
|
||||||
|
}
|
||||||
|
bool try_send(std::string const & str, std::uint64_t tm = default_timeout) {
|
||||||
|
return this->try_send(str.c_str(), str.size() + 1, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
buff_t recv(std::uint64_t tm = invalid_value) {
|
||||||
|
return detail_t::recv(h_, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
buff_t try_recv() {
|
||||||
|
return detail_t::try_recv(h_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <relat Rp, relat Rc, trans Ts>
|
||||||
|
using chan = chan_wrapper<ipc::wr<Rp, Rc, Ts>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class route
|
||||||
|
*
|
||||||
|
* You could use one producer/server/sender for sending messages to a route,
|
||||||
|
* then all the consumers/clients/receivers which are receiving with this route,
|
||||||
|
* would receive your sent messages.
|
||||||
|
*
|
||||||
|
* A route could only be used in 1 to N
|
||||||
|
* (one producer/writer to multi consumers/readers)
|
||||||
|
*/
|
||||||
|
|
||||||
|
using route = chan<relat::single, relat::multi, trans::broadcast>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* class channel
|
||||||
|
*
|
||||||
|
* You could use multi producers/writers for sending messages to a channel,
|
||||||
|
* then all the consumers/readers which are receiving with this channel,
|
||||||
|
* would receive your sent messages.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using channel = chan<relat::multi, relat::multi, trans::broadcast>;
|
||||||
|
|
||||||
|
} // namespace ipc
|
39
ipc/3rdparty/include/libipc/mutex.h
vendored
Normal file
39
ipc/3rdparty/include/libipc/mutex.h
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // std::uint64_t
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
#include "libipc/def.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
namespace sync {
|
||||||
|
|
||||||
|
class IPC_EXPORT mutex {
|
||||||
|
mutex(mutex const &) = delete;
|
||||||
|
mutex &operator=(mutex const &) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
mutex();
|
||||||
|
explicit mutex(char const *name);
|
||||||
|
~mutex();
|
||||||
|
|
||||||
|
void const *native() const noexcept;
|
||||||
|
void *native() noexcept;
|
||||||
|
|
||||||
|
bool valid() const noexcept;
|
||||||
|
|
||||||
|
bool open(char const *name) noexcept;
|
||||||
|
void close() noexcept;
|
||||||
|
|
||||||
|
bool lock(std::uint64_t tm = ipc::invalid_value) noexcept;
|
||||||
|
bool try_lock() noexcept(false); // std::system_error
|
||||||
|
bool unlock() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class mutex_;
|
||||||
|
mutex_* p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sync
|
||||||
|
} // namespace ipc
|
103
ipc/3rdparty/include/libipc/pool_alloc.h
vendored
Normal file
103
ipc/3rdparty/include/libipc/pool_alloc.h
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
#include "libipc/def.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
namespace mem {
|
||||||
|
|
||||||
|
class IPC_EXPORT pool_alloc {
|
||||||
|
public:
|
||||||
|
static void* alloc(std::size_t size);
|
||||||
|
static void free (void* p, std::size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
/// construct/destruct an object
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct impl {
|
||||||
|
template <typename... P>
|
||||||
|
static T* construct(T* p, P&&... params) {
|
||||||
|
::new (p) T(std::forward<P>(params)...);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destruct(T* p) {
|
||||||
|
reinterpret_cast<T*>(p)->~T();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
struct impl<T[N]> {
|
||||||
|
using type = T[N];
|
||||||
|
|
||||||
|
template <typename... P>
|
||||||
|
static type* construct(type* p, P&&... params) {
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
impl<T>::construct(&((*p)[i]), std::forward<P>(params)...);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destruct(type* p) {
|
||||||
|
for (size_t i = 0; i < N; ++i) {
|
||||||
|
impl<T>::destruct(&((*p)[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template <typename T, typename... P>
|
||||||
|
T* construct(T* p, P&&... params) {
|
||||||
|
return detail::impl<T>::construct(p, std::forward<P>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... P>
|
||||||
|
T* construct(void* p, P&&... params) {
|
||||||
|
return construct(static_cast<T*>(p), std::forward<P>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void destruct(T* p) {
|
||||||
|
return detail::impl<T>::destruct(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void destruct(void* p) {
|
||||||
|
destruct(static_cast<T*>(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
/// general alloc/free
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
inline void* alloc(std::size_t size) {
|
||||||
|
return pool_alloc::alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename... P>
|
||||||
|
T* alloc(P&&... params) {
|
||||||
|
return construct<T>(pool_alloc::alloc(sizeof(T)), std::forward<P>(params)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void free(void* p, std::size_t size) {
|
||||||
|
pool_alloc::free(p, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void free(T* p) {
|
||||||
|
if (p == nullptr) return;
|
||||||
|
destruct(p);
|
||||||
|
pool_alloc::free(p, sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mem
|
||||||
|
} // namespace ipc
|
171
ipc/3rdparty/include/libipc/rw_lock.h
vendored
Normal file
171
ipc/3rdparty/include/libipc/rw_lock.h
vendored
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
/// Gives hint to processor that improves performance of spin-wait loops.
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma push_macro("IPC_LOCK_PAUSE_")
|
||||||
|
#undef IPC_LOCK_PAUSE_
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <windows.h> // YieldProcessor
|
||||||
|
/*
|
||||||
|
See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms687419(v=vs.85).aspx
|
||||||
|
Not for intel c++ compiler, so ignore http://software.intel.com/en-us/forums/topic/296168
|
||||||
|
*/
|
||||||
|
# define IPC_LOCK_PAUSE_() YieldProcessor()
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
/*
|
||||||
|
See: Intel(R) 64 and IA-32 Architectures Software Developer's Manual V2
|
||||||
|
PAUSE-Spin Loop Hint, 4-57
|
||||||
|
http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.html?wapkw=instruction+set+reference
|
||||||
|
*/
|
||||||
|
# define IPC_LOCK_PAUSE_() __asm__ __volatile__("pause")
|
||||||
|
#elif defined(__ia64__) || defined(__ia64)
|
||||||
|
/*
|
||||||
|
See: Intel(R) Itanium(R) Architecture Developer's Manual, Vol.3
|
||||||
|
hint - Performance Hint, 3:145
|
||||||
|
http://www.intel.com/content/www/us/en/processors/itanium/itanium-architecture-vol-3-manual.html
|
||||||
|
*/
|
||||||
|
# define IPC_LOCK_PAUSE_() __asm__ __volatile__ ("hint @pause")
|
||||||
|
#elif defined(__arm__)
|
||||||
|
/*
|
||||||
|
See: ARM Architecture Reference Manuals (YIELD)
|
||||||
|
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.architecture.reference/index.html
|
||||||
|
*/
|
||||||
|
# define IPC_LOCK_PAUSE_() __asm__ __volatile__ ("yield")
|
||||||
|
#endif
|
||||||
|
#endif/*compilers*/
|
||||||
|
|
||||||
|
#if !defined(IPC_LOCK_PAUSE_)
|
||||||
|
/*
|
||||||
|
Just use a compiler fence, prevent compiler from optimizing loop
|
||||||
|
*/
|
||||||
|
# define IPC_LOCK_PAUSE_() std::atomic_signal_fence(std::memory_order_seq_cst)
|
||||||
|
#endif/*!defined(IPC_LOCK_PAUSE_)*/
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
/// Yield to other threads
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
inline void yield(K& k) noexcept {
|
||||||
|
if (k < 4) { /* Do nothing */ }
|
||||||
|
else
|
||||||
|
if (k < 16) { IPC_LOCK_PAUSE_(); }
|
||||||
|
else
|
||||||
|
if (k < 32) { std::this_thread::yield(); }
|
||||||
|
else {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t N = 32, typename K, typename F>
|
||||||
|
inline void sleep(K& k, F&& f) {
|
||||||
|
if (k < static_cast<K>(N)) {
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
static_cast<void>(std::forward<F>(f)());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t N = 32, typename K>
|
||||||
|
inline void sleep(K& k) {
|
||||||
|
sleep<N>(k, [] {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ipc
|
||||||
|
|
||||||
|
#pragma pop_macro("IPC_LOCK_PAUSE_")
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
|
||||||
|
class spin_lock {
|
||||||
|
std::atomic<unsigned> lc_ { 0 };
|
||||||
|
|
||||||
|
public:
|
||||||
|
void lock(void) noexcept {
|
||||||
|
for (unsigned k = 0;
|
||||||
|
lc_.exchange(1, std::memory_order_acquire);
|
||||||
|
yield(k)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock(void) noexcept {
|
||||||
|
lc_.store(0, std::memory_order_release);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class rw_lock {
|
||||||
|
using lc_ui_t = unsigned;
|
||||||
|
|
||||||
|
std::atomic<lc_ui_t> lc_ { 0 };
|
||||||
|
|
||||||
|
enum : lc_ui_t {
|
||||||
|
w_mask = (std::numeric_limits<std::make_signed_t<lc_ui_t>>::max)(), // b 0111 1111
|
||||||
|
w_flag = w_mask + 1 // b 1000 0000
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
rw_lock() = default;
|
||||||
|
|
||||||
|
rw_lock(const rw_lock&) = delete;
|
||||||
|
rw_lock& operator=(const rw_lock&) = delete;
|
||||||
|
rw_lock(rw_lock&&) = delete;
|
||||||
|
rw_lock& operator=(rw_lock&&) = delete;
|
||||||
|
|
||||||
|
void lock() noexcept {
|
||||||
|
for (unsigned k = 0;;) {
|
||||||
|
auto old = lc_.fetch_or(w_flag, std::memory_order_acq_rel);
|
||||||
|
if (!old) return; // got w-lock
|
||||||
|
if (!(old & w_flag)) break; // other thread having r-lock
|
||||||
|
yield(k); // other thread having w-lock
|
||||||
|
}
|
||||||
|
// wait for reading finished
|
||||||
|
for (unsigned k = 0;
|
||||||
|
lc_.load(std::memory_order_acquire) & w_mask;
|
||||||
|
yield(k)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock() noexcept {
|
||||||
|
lc_.store(0, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock_shared() noexcept {
|
||||||
|
auto old = lc_.load(std::memory_order_acquire);
|
||||||
|
for (unsigned k = 0;;) {
|
||||||
|
// if w_flag set, just continue
|
||||||
|
if (old & w_flag) {
|
||||||
|
yield(k);
|
||||||
|
old = lc_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
// otherwise try cas lc + 1 (set r-lock)
|
||||||
|
else if (lc_.compare_exchange_weak(old, old + 1, std::memory_order_release)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// set r-lock failed, old has been updated
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unlock_shared() noexcept {
|
||||||
|
lc_.fetch_sub(1, std::memory_order_release);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ipc
|
37
ipc/3rdparty/include/libipc/semaphore.h
vendored
Normal file
37
ipc/3rdparty/include/libipc/semaphore.h
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint> // std::uint64_t
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
#include "libipc/def.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
namespace sync {
|
||||||
|
|
||||||
|
class IPC_EXPORT semaphore {
|
||||||
|
semaphore(semaphore const &) = delete;
|
||||||
|
semaphore &operator=(semaphore const &) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
semaphore();
|
||||||
|
explicit semaphore(char const *name, std::uint32_t count = 0);
|
||||||
|
~semaphore();
|
||||||
|
|
||||||
|
void const *native() const noexcept;
|
||||||
|
void *native() noexcept;
|
||||||
|
|
||||||
|
bool valid() const noexcept;
|
||||||
|
|
||||||
|
bool open(char const *name, std::uint32_t count = 0) noexcept;
|
||||||
|
void close() noexcept;
|
||||||
|
|
||||||
|
bool wait(std::uint64_t tm = ipc::invalid_value) noexcept;
|
||||||
|
bool post(std::uint32_t count = 1) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class semaphore_;
|
||||||
|
semaphore_* p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sync
|
||||||
|
} // namespace ipc
|
59
ipc/3rdparty/include/libipc/shm.h
vendored
Normal file
59
ipc/3rdparty/include/libipc/shm.h
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "libipc/export.h"
|
||||||
|
|
||||||
|
namespace ipc {
|
||||||
|
namespace shm {
|
||||||
|
|
||||||
|
using id_t = void*;
|
||||||
|
|
||||||
|
enum : unsigned {
|
||||||
|
create = 0x01,
|
||||||
|
open = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
IPC_EXPORT id_t acquire(char const * name, std::size_t size, unsigned mode = create | open);
|
||||||
|
IPC_EXPORT void * get_mem(id_t id, std::size_t * size);
|
||||||
|
IPC_EXPORT std::int32_t release(id_t id);
|
||||||
|
IPC_EXPORT void remove (id_t id);
|
||||||
|
IPC_EXPORT void remove (char const * name);
|
||||||
|
|
||||||
|
IPC_EXPORT std::int32_t get_ref(id_t id);
|
||||||
|
IPC_EXPORT void sub_ref(id_t id);
|
||||||
|
|
||||||
|
class IPC_EXPORT handle {
|
||||||
|
public:
|
||||||
|
handle();
|
||||||
|
handle(char const * name, std::size_t size, unsigned mode = create | open);
|
||||||
|
handle(handle&& rhs);
|
||||||
|
|
||||||
|
~handle();
|
||||||
|
|
||||||
|
void swap(handle& rhs);
|
||||||
|
handle& operator=(handle rhs);
|
||||||
|
|
||||||
|
bool valid() const noexcept;
|
||||||
|
std::size_t size () const noexcept;
|
||||||
|
char const * name () const noexcept;
|
||||||
|
|
||||||
|
std::int32_t ref() const noexcept;
|
||||||
|
void sub_ref() noexcept;
|
||||||
|
|
||||||
|
bool acquire(char const * name, std::size_t size, unsigned mode = create | open);
|
||||||
|
std::int32_t release();
|
||||||
|
|
||||||
|
void* get() const;
|
||||||
|
|
||||||
|
void attach(id_t);
|
||||||
|
id_t detach();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class handle_;
|
||||||
|
handle_* p_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace shm
|
||||||
|
} // namespace ipc
|
BIN
ipc/3rdparty/lib/ipc.lib
vendored
Normal file
BIN
ipc/3rdparty/lib/ipc.lib
vendored
Normal file
Binary file not shown.
BIN
ipc/3rdparty/lib/ipc_o.lib
vendored
Normal file
BIN
ipc/3rdparty/lib/ipc_o.lib
vendored
Normal file
Binary file not shown.
BIN
ipc/3rdparty/lib/ipcd.lib
vendored
Normal file
BIN
ipc/3rdparty/lib/ipcd.lib
vendored
Normal file
Binary file not shown.
BIN
ipc/3rdparty/lib/ipcd.pdb
vendored
Normal file
BIN
ipc/3rdparty/lib/ipcd.pdb
vendored
Normal file
Binary file not shown.
103
ipc/Ipc.cpp
Normal file
103
ipc/Ipc.cpp
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
#include "Ipc.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "ReadCallback.h"
|
||||||
|
|
||||||
|
std::shared_ptr<Ipc> Ipc::create(const char* reader_name, const char* writer_name) {
|
||||||
|
struct Creator : public Ipc {
|
||||||
|
Creator(const char* reader_name, const char* writer_name) : Ipc(reader_name, writer_name) {}
|
||||||
|
~Creator() override = default;
|
||||||
|
};
|
||||||
|
return std::make_shared<Creator>(reader_name, writer_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ipc::Ipc(const char* reader_name, const char* writer_name) noexcept
|
||||||
|
: reader_name_(reader_name)
|
||||||
|
, writer_name_(writer_name) {
|
||||||
|
sender_ = std::make_unique<ipc::channel>(reader_name_.c_str(), ipc::sender);
|
||||||
|
printf("%s, %s", reader_name, writer_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ipc::~Ipc() {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ipc::listen() {
|
||||||
|
if (reciver_stop_.load(std::memory_order_acquire)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
reciver_stop_.store(false);
|
||||||
|
|
||||||
|
std::weak_ptr<Ipc> wThis = shared_from_this();
|
||||||
|
reciver_thread_ = std::move(std::thread(std::bind(&Ipc::doReciver, this, wThis)));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ipc::stop() {
|
||||||
|
if (!reciver_stop_.load(std::memory_order_acquire)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reciver_stop_.store(true, std::memory_order_release);
|
||||||
|
|
||||||
|
sender_->disconnect();
|
||||||
|
receiver_->disconnect();
|
||||||
|
|
||||||
|
if (reciver_thread_.joinable()) {
|
||||||
|
reciver_thread_.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ipc::send(const char* data, unsigned int size) {
|
||||||
|
if (!sender_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sender_->send(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ipc::registReadCallback(const std::shared_ptr<IReaderCallback>& reader) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
|
auto itor = std::find(reader_callbacks_.begin(), reader_callbacks_.end(), reader);
|
||||||
|
if (reader_callbacks_.end() != itor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reader_callbacks_.emplace_back(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ipc::unregistReadCallback(const std::shared_ptr<IReaderCallback>& reader) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
|
||||||
|
auto itor = std::find(reader_callbacks_.begin(), reader_callbacks_.end(), reader);
|
||||||
|
if (reader_callbacks_.end() != itor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reader_callbacks_.erase(itor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ipc::doReciver(std::weak_ptr<Ipc> wThis) {
|
||||||
|
std::shared_ptr<Ipc> self(wThis.lock());
|
||||||
|
if (!self) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
receiver_ = std::make_unique<ipc::channel>(writer_name_.c_str(), ipc::receiver);
|
||||||
|
while (!reciver_stop_.load(std::memory_order_acquire)) {
|
||||||
|
ipc::buff_t buffer = receiver_->recv();
|
||||||
|
if (buffer.empty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const char* data = buffer.get<const char*>();
|
||||||
|
onReciveer(data, static_cast<unsigned int>(buffer.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ipc::onReciveer(const char* buffer, unsigned int size) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
for (auto& read : reader_callbacks_) {
|
||||||
|
read->onRead(buffer, size);
|
||||||
|
}
|
||||||
|
}
|
45
ipc/Ipc.h
Normal file
45
ipc/Ipc.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <libipc/ipc.h>
|
||||||
|
#include <memory>
|
||||||
|
#include <atomic>
|
||||||
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
class IReaderCallback;
|
||||||
|
|
||||||
|
class Ipc : public std::enable_shared_from_this<Ipc>{
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<Ipc> create(const char* reader_name, const char* writer_name);
|
||||||
|
public:
|
||||||
|
virtual ~Ipc();
|
||||||
|
|
||||||
|
bool listen();
|
||||||
|
void stop();
|
||||||
|
bool send(const char* data, unsigned int size);
|
||||||
|
|
||||||
|
void registReadCallback(const std::shared_ptr<IReaderCallback>& reader);
|
||||||
|
void unregistReadCallback(const std::shared_ptr<IReaderCallback>& reader);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Ipc(const char* reader_name, const char* writer_name) noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void doReciver(std::weak_ptr<Ipc> wThis);
|
||||||
|
|
||||||
|
void onReciveer(const char* buffer, unsigned int size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string reader_name_;
|
||||||
|
std::string writer_name_;
|
||||||
|
std::unique_ptr<ipc::channel> sender_;
|
||||||
|
std::unique_ptr<ipc::channel> receiver_;
|
||||||
|
std::thread reciver_thread_;
|
||||||
|
std::atomic_bool reciver_stop_{false};
|
||||||
|
|
||||||
|
std::mutex mutex_;
|
||||||
|
using ReaderCallbackList = std::vector<std::shared_ptr<IReaderCallback>>;
|
||||||
|
ReaderCallbackList reader_callbacks_;
|
||||||
|
};
|
||||||
|
|
9
ipc/ReadCallback.h
Normal file
9
ipc/ReadCallback.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class IReaderCallback {
|
||||||
|
public:
|
||||||
|
virtual ~IReaderCallback() = default;
|
||||||
|
|
||||||
|
// read thread callback
|
||||||
|
virtual void onRead(const char* buffer, unsigned int size) = 0;
|
||||||
|
};
|
20
ipc/include/config.h
Normal file
20
ipc/include/config.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _IPC_EXPORT_
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#define IPC_EXPORT __declspec( dllexport )
|
||||||
|
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#define IPC_EXPORT __declspec( dllimport )
|
||||||
|
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
#endif // _IPC_EXPORT_
|
||||||
|
|
21
ipc/include/ipclib.h
Normal file
21
ipc/include/ipclib.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
typedef void(__stdcall *ReaderCallbackFunc)(const char* data, unsigned int size);
|
||||||
|
|
||||||
|
IPC_EXPORT bool __stdcall initialize(const char* sender_name, const char* receiver_name);
|
||||||
|
IPC_EXPORT void __stdcall uninitialize();
|
||||||
|
|
||||||
|
IPC_EXPORT bool __stdcall listen();
|
||||||
|
IPC_EXPORT bool __stdcall send(const char* data, unsigned int size);
|
||||||
|
IPC_EXPORT bool __stdcall setReaderCallback(ReaderCallbackFunc callback);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif // __cplusplus
|
69
ipc/ipclib.cpp
Normal file
69
ipc/ipclib.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "include/ipclib.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "Ipc.h"
|
||||||
|
#include "ReadCallback.h"
|
||||||
|
|
||||||
|
class ReaderCallback : public IReaderCallback {
|
||||||
|
public:
|
||||||
|
ReaderCallback() = default;
|
||||||
|
~ReaderCallback() override = default;
|
||||||
|
void onRead(const char* buffer, unsigned int size) override {
|
||||||
|
printf("%s", buffer);
|
||||||
|
if (nullptr != m_readerCallbackFunc) {
|
||||||
|
m_readerCallbackFunc(buffer, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCallback(ReaderCallbackFunc func) {
|
||||||
|
m_readerCallbackFunc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReaderCallback(const ReaderCallback&) = delete;
|
||||||
|
ReaderCallback operator= (const ReaderCallback&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReaderCallbackFunc m_readerCallbackFunc{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Ipc> g_ipc;
|
||||||
|
std::shared_ptr<ReaderCallback> g_readCallback;
|
||||||
|
|
||||||
|
bool __stdcall initialize(const char* sender_name, const char* receiver_name) {
|
||||||
|
assert(!g_ipc);
|
||||||
|
g_ipc = Ipc::create(sender_name, receiver_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __stdcall uninitialize() {
|
||||||
|
assert(g_ipc);
|
||||||
|
g_ipc->stop();
|
||||||
|
if (g_readCallback) {
|
||||||
|
g_ipc->unregistReadCallback(g_readCallback);
|
||||||
|
g_readCallback.reset();
|
||||||
|
}
|
||||||
|
g_ipc.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __stdcall listen() {
|
||||||
|
assert(g_ipc);
|
||||||
|
return g_ipc->listen();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __stdcall send(const char* data, unsigned int size) {
|
||||||
|
assert(g_ipc);
|
||||||
|
return g_ipc->send(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __stdcall setReaderCallback(ReaderCallbackFunc callback) {
|
||||||
|
assert(g_ipc);
|
||||||
|
if (!g_readCallback) {
|
||||||
|
g_readCallback = std::make_shared<ReaderCallback>();
|
||||||
|
g_ipc->registReadCallback(g_readCallback);
|
||||||
|
}
|
||||||
|
g_readCallback->setCallback(callback);
|
||||||
|
return true;
|
||||||
|
}
|
BIN
x64/Debug/ipc.dll
Normal file
BIN
x64/Debug/ipc.dll
Normal file
Binary file not shown.
BIN
x64/Debug/ipc.exp
Normal file
BIN
x64/Debug/ipc.exp
Normal file
Binary file not shown.
BIN
x64/Debug/ipc.lib
Normal file
BIN
x64/Debug/ipc.lib
Normal file
Binary file not shown.
BIN
x64/Debug/ipc.pdb
Normal file
BIN
x64/Debug/ipc.pdb
Normal file
Binary file not shown.
BIN
x64/Debug/ipcd.dll
Normal file
BIN
x64/Debug/ipcd.dll
Normal file
Binary file not shown.
BIN
x64/Debug/ipcd.exp
Normal file
BIN
x64/Debug/ipcd.exp
Normal file
Binary file not shown.
BIN
x64/Debug/ipcd.lib
Normal file
BIN
x64/Debug/ipcd.lib
Normal file
Binary file not shown.
BIN
x64/Debug/ipcd.pdb
Normal file
BIN
x64/Debug/ipcd.pdb
Normal file
Binary file not shown.
BIN
x64/Release/ipc.dll
Normal file
BIN
x64/Release/ipc.dll
Normal file
Binary file not shown.
BIN
x64/Release/ipc.exp
Normal file
BIN
x64/Release/ipc.exp
Normal file
Binary file not shown.
BIN
x64/Release/ipc.lib
Normal file
BIN
x64/Release/ipc.lib
Normal file
Binary file not shown.
BIN
x64/Release/ipc.pdb
Normal file
BIN
x64/Release/ipc.pdb
Normal file
Binary file not shown.
BIN
x64/Release/ipc_test.dll
Normal file
BIN
x64/Release/ipc_test.dll
Normal file
Binary file not shown.
BIN
x64/Release/ipc_test.exp
Normal file
BIN
x64/Release/ipc_test.exp
Normal file
Binary file not shown.
BIN
x64/Release/ipc_test.lib
Normal file
BIN
x64/Release/ipc_test.lib
Normal file
Binary file not shown.
BIN
x64/Release/ipc_test.pdb
Normal file
BIN
x64/Release/ipc_test.pdb
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user