Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mutouyun/cpp-ipc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.3.0
Choose a base ref
...
head repository: mutouyun/cpp-ipc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Dec 10, 2023

  1. Add cpp-ipc-targets

    winsoft666 authored and mutouyun committed Dec 10, 2023
    Copy the full SHA
    c4280ef View commit details
  2. Add PACKAGE_VERSION

    winsoft666 authored and mutouyun committed Dec 10, 2023
    Copy the full SHA
    144b2db View commit details
  3. Update CMakeLists.txt

    winsoft666 authored and mutouyun committed Dec 10, 2023
    Copy the full SHA
    035d76d View commit details

Commits on May 25, 2024

  1. Copy the full SHA
    025311d View commit details
  2. Copy the full SHA
    8054906 View commit details

Commits on Nov 17, 2024

  1. Copy the full SHA
    5071fb5 View commit details
  2. Copy the full SHA
    29678f1 View commit details
  3. Copy the full SHA
    e1f377d View commit details
  4. Fix ut

    mutouyun committed Nov 17, 2024
    Copy the full SHA
    acea9d7 View commit details

Commits on Dec 1, 2024

  1. Copy the full SHA
    ab90437 View commit details
  2. Copy the full SHA
    17dcde9 View commit details
  3. Copy the full SHA
    28fdf17 View commit details
  4. Copy the full SHA
    5e5b347 View commit details
  5. Copy the full SHA
    84bb801 View commit details
  6. Copy the full SHA
    2673453 View commit details

Commits on Feb 9, 2025

  1. Update README.md

    mutouyun authored Feb 9, 2025
    Copy the full SHA
    df09c22 View commit details

Commits on Mar 7, 2025

  1. Copy the full SHA
    d690934 View commit details
  2. posix shm open 失败时如果文件不存在打印log

    Aengus.Jiang committed Mar 7, 2025
    Copy the full SHA
    5c36b12 View commit details
  3. Copy the full SHA
    06d4aec View commit details
  4. Copy the full SHA
    7bb5f2e View commit details

Commits on Mar 8, 2025

  1. Merge pull request #139 from aengusjiang/master

    acquire 仅open不存在的shm不应该打印错误日志
    mutouyun authored Mar 8, 2025
    Copy the full SHA
    f3bf137 View commit details

Commits on Apr 20, 2025

  1. Update rw_lock.h for #143

    mutouyun authored Apr 20, 2025
    Copy the full SHA
    fdcc934 View commit details

Commits on Apr 23, 2025

  1. Copy the full SHA
    a6c7c85 View commit details

Commits on May 1, 2025

  1. Merge pull request #145 from johnwongx/sync

    修复连接槽满判断错误
    mutouyun authored May 1, 2025
    Copy the full SHA
    120d85a View commit details

Commits on May 9, 2025

  1. Fixed issue 107 and 123, receiver check connection when pop msg faile…

    …d, and call reconnect function when the connection check result is false
    yongke liu committed May 9, 2025
    Copy the full SHA
    87b1fa4 View commit details

Commits on May 10, 2025

  1. Copy the full SHA
    a1cdc9a View commit details

Commits on May 11, 2025

  1. Merge pull request #148 from mutouyun/yonker-yk-master

    Yonker yk master
    mutouyun authored May 11, 2025
    Copy the full SHA
    a0c7725 View commit details
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
* No other dependencies except STL.
* Only lock-free or lightweight spin-lock is used.
* Circular array is used as the underline data structure.
* `ipc::route` supports single read and multiple write. `ipc::channel` supports multiple read and write. (**Note: currently, a channel supports up to 32 receivers, but there is no such a limit for the sender.**)
* `ipc::route` supports single write and multiple read. `ipc::channel` supports multiple read and write. (**Note: currently, a channel supports up to 32 receivers, but there is no such a limit for the sender.**)
* Broadcasting is used by default, but user can choose any read/ write combinations.
* No long time blind wait. (Semaphore will be used after a certain number of retries.)
* [Vcpkg](https://github.com/microsoft/vcpkg/blob/master/README.md) way of installation is supported. E.g. `vcpkg install cpp-ipc`
3 changes: 3 additions & 0 deletions include/libipc/condition.h
Original file line number Diff line number Diff line change
@@ -26,6 +26,9 @@ class IPC_EXPORT condition {
bool open(char const *name) noexcept;
void close() noexcept;

void clear() noexcept;
static void clear_storage(char const * name) noexcept;

bool wait(ipc::sync::mutex &mtx, std::uint64_t tm = ipc::invalid_value) noexcept;
bool notify(ipc::sync::mutex &mtx) noexcept;
bool broadcast(ipc::sync::mutex &mtx) noexcept;
38 changes: 34 additions & 4 deletions include/libipc/ipc.h
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ enum : unsigned {

template <typename Flag>
struct IPC_EXPORT chan_impl {
static ipc::handle_t inited();
static ipc::handle_t init_first();

static bool connect (ipc::handle_t * ph, char const * name, unsigned mode);
static bool connect (ipc::handle_t * ph, prefix, char const * name, unsigned mode);
@@ -29,8 +29,16 @@ struct IPC_EXPORT chan_impl {

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);
// Release memory without waiting for the connection to disconnect.
static void release(ipc::handle_t h) noexcept;

// Force cleanup of all shared memory storage that handles depend on.
static void clear(ipc::handle_t h) noexcept;
static void clear_storage(char const * name) noexcept;
static void clear_storage(prefix, char const * name) noexcept;

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);
@@ -44,7 +52,7 @@ class chan_wrapper {
private:
using detail_t = chan_impl<Flag>;

ipc::handle_t h_ = detail_t::inited();
ipc::handle_t h_ = detail_t::init_first();
unsigned mode_ = ipc::sender;
bool connected_ = false;

@@ -83,6 +91,28 @@ class chan_wrapper {
return detail_t::name(h_);
}

// Release memory without waiting for the connection to disconnect.
void release() noexcept {
detail_t::release(h_);
h_ = nullptr;
}

// Clear shared memory files under opened handle.
void clear() noexcept {
detail_t::clear(h_);
h_ = nullptr;
}

// Clear shared memory files under a specific name.
static void clear_storage(char const * name) noexcept {
detail_t::clear_storage(name);
}

// Clear shared memory files under a specific name with a prefix.
static void clear_storage(prefix pref, char const * name) noexcept {
detail_t::clear_storage(pref, name);
}

ipc::handle_t handle() const noexcept {
return h_;
}
3 changes: 3 additions & 0 deletions include/libipc/mutex.h
Original file line number Diff line number Diff line change
@@ -26,6 +26,9 @@ class IPC_EXPORT mutex {
bool open(char const *name) noexcept;
void close() noexcept;

void clear() noexcept;
static void clear_storage(char const * name) noexcept;

bool lock(std::uint64_t tm = ipc::invalid_value) noexcept;
bool try_lock() noexcept(false); // std::system_error
bool unlock() noexcept;
4 changes: 2 additions & 2 deletions include/libipc/pool_alloc.h
Original file line number Diff line number Diff line change
@@ -11,8 +11,8 @@ namespace mem {

class IPC_EXPORT pool_alloc {
public:
static void* alloc(std::size_t size);
static void free (void* p, std::size_t size);
static void* alloc(std::size_t size) noexcept;
static void free (void* p, std::size_t size) noexcept;
};

////////////////////////////////////////////////////////////////
9 changes: 5 additions & 4 deletions include/libipc/rw_lock.h
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
#include <limits>
#include <type_traits>
#include <utility>
#include <cstdint>

////////////////////////////////////////////////////////////////
/// Gives hint to processor that improves performance of spin-wait loops.
@@ -98,7 +99,7 @@ inline void sleep(K& k) {
namespace ipc {

class spin_lock {
std::atomic<unsigned> lc_ { 0 };
std::atomic<std::uint32_t> lc_ { 0 };

public:
void lock(void) noexcept {
@@ -113,13 +114,13 @@ class spin_lock {
};

class rw_lock {
using lc_ui_t = unsigned;
using lc_ui_t = std::uint32_t;

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
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:
3 changes: 3 additions & 0 deletions include/libipc/semaphore.h
Original file line number Diff line number Diff line change
@@ -25,6 +25,9 @@ class IPC_EXPORT semaphore {
bool open(char const *name, std::uint32_t count = 0) noexcept;
void close() noexcept;

void clear() noexcept;
static void clear_storage(char const * name) noexcept;

bool wait(std::uint64_t tm = ipc::invalid_value) noexcept;
bool post(std::uint32_t count = 1) noexcept;

10 changes: 7 additions & 3 deletions include/libipc/shm.h
Original file line number Diff line number Diff line change
@@ -17,9 +17,9 @@ enum : unsigned {

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 release(id_t id) noexcept;
IPC_EXPORT void remove (id_t id) noexcept;
IPC_EXPORT void remove (char const * name) noexcept;

IPC_EXPORT std::int32_t get_ref(id_t id);
IPC_EXPORT void sub_ref(id_t id);
@@ -45,6 +45,10 @@ class IPC_EXPORT handle {
bool acquire(char const * name, std::size_t size, unsigned mode = create | open);
std::int32_t release();

// Clean the handle file.
void clear() noexcept;
static void clear_storage(char const * name) noexcept;

void* get() const;

void attach(id_t);
30 changes: 28 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
project(ipc)

set (PACKAGE_VERSION 1.3.0)

aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc SRC_FILES)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/sync SRC_FILES)
aux_source_directory(${LIBIPC_PROJECT_DIR}/src/libipc/platform SRC_FILES)
@@ -34,11 +36,13 @@ set_target_properties(${PROJECT_NAME}
# set version
set_target_properties(${PROJECT_NAME}
PROPERTIES
VERSION 1.2.0
VERSION ${PACKAGE_VERSION}
SOVERSION 3)

target_include_directories(${PROJECT_NAME}
PUBLIC ${LIBIPC_PROJECT_DIR}/include
PUBLIC
"$<BUILD_INTERFACE:${LIBIPC_PROJECT_DIR}/include>"
"$<INSTALL_INTERFACE:include>"
PRIVATE ${LIBIPC_PROJECT_DIR}/src
$<$<BOOL:UNIX>:${LIBIPC_PROJECT_DIR}/src/libipc/platform/linux>)

@@ -50,6 +54,28 @@ endif()

install(
TARGETS ${PROJECT_NAME}
EXPORT cpp-ipc-targets
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)

install(EXPORT cpp-ipc-targets
FILE cpp-ipc-targets.cmake
NAMESPACE cpp-ipc::
DESTINATION share/cpp-ipc
)

file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cpp-ipc-config.cmake.in"
[[include(CMakeFindDependencyMacro)
include("${CMAKE_CURRENT_LIST_DIR}/cpp-ipc-targets.cmake")
]])
configure_file("${CMAKE_CURRENT_BINARY_DIR}/cpp-ipc-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cpp-ipc-config.cmake" @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cpp-ipc-config.cmake DESTINATION share/cpp-ipc)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
cppIpcConfigVersion.cmake
VERSION ${PACKAGE_VERSION}
COMPATIBILITY AnyNewerVersion
)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cppIpcConfigVersion.cmake DESTINATION share/cpp-ipc)
11 changes: 10 additions & 1 deletion src/libipc/circ/elem_def.h
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ class conn_head<P, true> : public conn_head_base {
for (unsigned k = 0;; ipc::yield(k)) {
cc_t curr = this->cc_.load(std::memory_order_acquire);
cc_t next = curr | (curr + 1); // find the first 0, and set it to 1.
if (next == 0) {
if (next == curr) {
// connection-slot is full.
return 0;
}
@@ -74,6 +74,10 @@ class conn_head<P, true> : public conn_head_base {
return this->cc_.fetch_and(~cc_id, std::memory_order_acq_rel) & ~cc_id;
}

bool connected(cc_t cc_id) const noexcept {
return (this->connections() & cc_id) != 0;
}

std::size_t conn_count(std::memory_order order = std::memory_order_acquire) const noexcept {
cc_t cur = this->cc_.load(order);
cc_t cnt; // accumulates the total bits set in cc
@@ -100,6 +104,11 @@ class conn_head<P, false> : public conn_head_base {
}
}

bool connected(cc_t cc_id) const noexcept {
// In non-broadcast mode, connection tags are only used for counting.
return (this->connections() != 0) && (cc_id != 0);
}

std::size_t conn_count(std::memory_order order = std::memory_order_acquire) const noexcept {
return this->connections(order);
}
75 changes: 67 additions & 8 deletions src/libipc/ipc.cpp
Original file line number Diff line number Diff line change
@@ -136,6 +136,22 @@ struct conn_info_head {
}
}

void clear() noexcept {
cc_waiter_.clear();
wt_waiter_.clear();
rd_waiter_.clear();
acc_h_.clear();
}

static void clear_storage(char const * prefix, char const * name) noexcept {
auto p = ipc::make_string(prefix);
auto n = ipc::make_string(name);
ipc::detail::waiter::clear_storage(ipc::make_prefix(p, {"CC_CONN__", n}).c_str());
ipc::detail::waiter::clear_storage(ipc::make_prefix(p, {"WT_CONN__", n}).c_str());
ipc::detail::waiter::clear_storage(ipc::make_prefix(p, {"RD_CONN__", n}).c_str());
ipc::shm::handle::clear_storage(ipc::make_prefix(p, {"AC_CONN__", n}).c_str());
}

void quit_waiting() {
cc_waiter_.quit_waiting();
wt_waiter_.quit_waiting();
@@ -379,13 +395,27 @@ struct queue_generator {
conn_info_head::init();
if (!que_.valid()) {
que_.open(ipc::make_prefix(prefix_, {
"QU_CONN__",
ipc::to_string(DataSize), "__",
ipc::to_string(AlignSize), "__",
this->name_}).c_str());
"QU_CONN__",
this->name_,
"__", ipc::to_string(DataSize),
"__", ipc::to_string(AlignSize)}).c_str());
}
}

void clear() noexcept {
que_.clear();
conn_info_head::clear();
}

static void clear_storage(char const * prefix, char const * name) noexcept {
queue_t::clear_storage(ipc::make_prefix(ipc::make_string(prefix), {
"QU_CONN__",
ipc::make_string(name),
"__", ipc::to_string(DataSize),
"__", ipc::to_string(AlignSize)}).c_str());
conn_info_head::clear_storage(prefix, name);
}

void disconnect_receiver() {
bool dis = que_.disconnect();
this->quit_waiting();
@@ -459,8 +489,7 @@ static bool reconnect(ipc::handle_t * ph, bool start_to_recv) {
return que->ready_sending();
}

static void destroy(ipc::handle_t h) {
disconnect(h);
static void destroy(ipc::handle_t h) noexcept {
ipc::mem::free(info_of(h));
}

@@ -598,7 +627,10 @@ static ipc::buff_t recv(ipc::handle_t h, std::uint64_t tm) {
for (;;) {
// pop a new message
typename queue_t::value_t msg {};
if (!wait_for(inf->rd_waiter_, [que, &msg] {
if (!wait_for(inf->rd_waiter_, [que, &msg, &h] {
if (!que->connected()) {
reconnect(&h, true);
}
return !que->pop(msg);
}, tm)) {
// pop failed, just return.
@@ -703,7 +735,7 @@ using policy_t = ipc::policy::choose<ipc::circ::elem_array, Flag>;
namespace ipc {

template <typename Flag>
ipc::handle_t chan_impl<Flag>::inited() {
ipc::handle_t chan_impl<Flag>::init_first() {
ipc::detail::waiter::init();
return nullptr;
}
@@ -730,6 +762,12 @@ void chan_impl<Flag>::disconnect(ipc::handle_t h) {

template <typename Flag>
void chan_impl<Flag>::destroy(ipc::handle_t h) {
disconnect(h);
detail_impl<policy_t<Flag>>::destroy(h);
}

template <typename Flag>
void chan_impl<Flag>::release(ipc::handle_t h) noexcept {
detail_impl<policy_t<Flag>>::destroy(h);
}

@@ -739,6 +777,27 @@ char const * chan_impl<Flag>::name(ipc::handle_t h) {
return (info == nullptr) ? nullptr : info->name_.c_str();
}

template <typename Flag>
void chan_impl<Flag>::clear(ipc::handle_t h) noexcept {
disconnect(h);
using conn_info_t = typename detail_impl<policy_t<Flag>>::conn_info_t;
auto conn_info_p = static_cast<conn_info_t *>(h);
if (conn_info_p == nullptr) return;
conn_info_p->clear();
destroy(h);
}

template <typename Flag>
void chan_impl<Flag>::clear_storage(char const * name) noexcept {
chan_impl<Flag>::clear_storage({nullptr}, name);
}

template <typename Flag>
void chan_impl<Flag>::clear_storage(prefix pref, char const * name) noexcept {
using conn_info_t = typename detail_impl<policy_t<Flag>>::conn_info_t;
conn_info_t::clear_storage(pref.str, name);
}

template <typename Flag>
std::size_t chan_impl<Flag>::recv_count(ipc::handle_t h) {
return detail_impl<policy_t<Flag>>::recv_count(h);
Loading