Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
17eaa57
chore(test): archive existing test cases to test/archive
mutouyun Nov 30, 2025
3d743d5
test(buffer): add comprehensive unit tests for ipc::buffer
mutouyun Nov 30, 2025
280a21c
test(shm): add comprehensive unit tests for shared memory
mutouyun Nov 30, 2025
b4ad3c6
test(mutex): add comprehensive unit tests for ipc::sync::mutex
mutouyun Nov 30, 2025
6e17ce1
test(semaphore): add comprehensive unit tests for ipc::sync::semaphore
mutouyun Nov 30, 2025
4832c47
test(condition): add comprehensive unit tests for ipc::sync::condition
mutouyun Nov 30, 2025
c21138b
test(locks): add comprehensive unit tests for spin_lock and rw_lock
mutouyun Nov 30, 2025
9070a89
test(ipc): add comprehensive unit tests for route and channel
mutouyun Nov 30, 2025
b514665
build(test): update CMakeLists.txt for new test structure
mutouyun Nov 30, 2025
2cde78d
style(test): change indentation from 4 spaces to 2 spaces
mutouyun Nov 30, 2025
7092df5
fix(test): resolve id_t ambiguity in test_shm.cpp
mutouyun Nov 30, 2025
7447a86
fix(test): correct member vs non-member function calls in test_shm.cpp
mutouyun Nov 30, 2025
8103c11
fix(buffer): remove redundant const qualifier in array constructor
mutouyun Nov 30, 2025
de76cf8
fix(buffer): remove const from char constructor to prevent UB
mutouyun Nov 30, 2025
91e4489
refactor(buffer): rename 'additional' parameter to 'mem_to_free' for …
mutouyun Nov 30, 2025
0ecf1a4
docs(shm): add semantic comments for release/remove and fix double-fr…
mutouyun Nov 30, 2025
d5f7875
fix(test): fix double-free in HandleDetachAttach test
mutouyun Nov 30, 2025
78be284
fix(test): correct test logic and semantics in multiple test cases
mutouyun Nov 30, 2025
ff74cdd
fix(test): correct receiver loop count in MultipleSendersReceivers
mutouyun Nov 30, 2025
e66bd88
fix(platform): resolve ODR violation in make_timespec/calc_wait_time …
mutouyun Nov 30, 2025
b9dd75c
fix(platform): rename linux/posix namespaces to avoid predefined macr…
mutouyun Nov 30, 2025
7726742
feat(shm): implement reference counting for Windows shared memory
mutouyun Nov 30, 2025
c31ef98
fix(shm): remove redundant self-assignment in shm_win.cpp
mutouyun Nov 30, 2025
cf5738e
fix(test): replace C++17 structured bindings with C++14 compatible code
mutouyun Nov 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions include/libipc/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ class IPC_EXPORT buffer {
buffer();

buffer(void* p, std::size_t s, destructor_t d);
buffer(void* p, std::size_t s, destructor_t d, void* additional);
// mem_to_free: pointer to be passed to destructor (if different from p)
// Use case: when p points into a larger allocated block that needs to be freed
buffer(void* p, std::size_t s, destructor_t d, void* mem_to_free);
buffer(void* p, std::size_t s);

template <std::size_t N>
explicit buffer(byte_t const (& data)[N])
explicit buffer(byte_t (& data)[N])
: buffer(data, sizeof(data)) {
}
explicit buffer(char const & c);
explicit buffer(char & c);

buffer(buffer&& rhs);
~buffer();
Expand Down
22 changes: 22 additions & 0 deletions include/libipc/shm.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,30 @@ 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);

// Release shared memory resource and clean up disk file if reference count reaches zero.
// This function decrements the reference counter. When the counter reaches zero, it:
// 1. Unmaps the shared memory region
// 2. Removes the backing file from disk (shm_unlink on POSIX)
// 3. Frees the id structure
// After calling this function, the id becomes invalid and must not be used again.
// Returns: The reference count before decrement, or -1 on error.
IPC_EXPORT std::int32_t release(id_t id) noexcept;

// Release shared memory resource and force cleanup of disk file.
// This function calls release(id) internally, then unconditionally attempts to
// remove the backing file. WARNING: Do NOT call this after release(id) on the
// same id, as the id is already freed by release(). Use this function alone,
// not in combination with release().
// Typical use case: Force cleanup when you want to ensure the disk file is removed
// regardless of reference count state.
IPC_EXPORT void remove (id_t id) noexcept;

// Remove shared memory backing file by name.
// This function only removes the disk file and does not affect any active memory
// mappings or id structures. Use this for cleanup of orphaned files or for explicit
// file removal without affecting runtime resources.
// Safe to call at any time, even if shared memory is still in use elsewhere.
IPC_EXPORT void remove (char const * name) noexcept;

IPC_EXPORT std::int32_t get_ref(id_t id);
Expand Down
8 changes: 4 additions & 4 deletions src/libipc/buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ buffer::buffer(void* p, std::size_t s, destructor_t d)
: p_(p_->make(p, s, d, nullptr)) {
}

buffer::buffer(void* p, std::size_t s, destructor_t d, void* additional)
: p_(p_->make(p, s, d, additional)) {
buffer::buffer(void* p, std::size_t s, destructor_t d, void* mem_to_free)
: p_(p_->make(p, s, d, mem_to_free)) {
}

buffer::buffer(void* p, std::size_t s)
: buffer(p, s, nullptr) {
}

buffer::buffer(char const & c)
: buffer(const_cast<char*>(&c), 1) {
buffer::buffer(char & c)
: buffer(&c, 1) {
}

buffer::buffer(buffer&& rhs)
Expand Down
2 changes: 1 addition & 1 deletion src/libipc/platform/linux/condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class condition : public sync::obj_impl<a0_cnd_t> {
return false;
}
} else {
auto ts = detail::make_timespec(tm);
auto ts = linux_::detail::make_timespec(tm);
int eno = A0_SYSERR(a0_cnd_timedwait(native(), static_cast<a0_mtx_t *>(mtx.native()), {ts}));
if (eno != 0) {
if (eno != ETIMEDOUT) {
Expand Down
2 changes: 2 additions & 0 deletions src/libipc/platform/linux/get_wait_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "a0/err_macro.h"

namespace ipc {
namespace linux_ {
namespace detail {

inline bool calc_wait_time(timespec &ts, std::uint64_t tm /*ms*/) noexcept {
Expand Down Expand Up @@ -43,4 +44,5 @@ inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) {
}

} // namespace detail
} // namespace linux_
} // namespace ipc
4 changes: 2 additions & 2 deletions src/libipc/platform/linux/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class robust_mutex : public sync::obj_impl<a0_mtx_t> {
bool lock(std::uint64_t tm) noexcept {
if (!valid()) return false;
for (;;) {
auto ts = detail::make_timespec(tm);
auto ts = linux_::detail::make_timespec(tm);
int eno = A0_SYSERR(
(tm == invalid_value) ? a0_mtx_lock(native())
: a0_mtx_timedlock(native(), {ts}));
Expand Down Expand Up @@ -56,7 +56,7 @@ class robust_mutex : public sync::obj_impl<a0_mtx_t> {

bool try_lock() noexcept(false) {
if (!valid()) return false;
int eno = A0_SYSERR(a0_mtx_timedlock(native(), {detail::make_timespec(0)}));
int eno = A0_SYSERR(a0_mtx_timedlock(native(), {linux_::detail::make_timespec(0)}));
switch (eno) {
case 0:
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/libipc/platform/posix/condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class condition {
}
break;
default: {
auto ts = detail::make_timespec(tm);
auto ts = posix_::detail::make_timespec(tm);
int eno;
if ((eno = ::pthread_cond_timedwait(cond_, static_cast<pthread_mutex_t *>(mtx.native()), &ts)) != 0) {
if (eno != ETIMEDOUT) {
Expand Down
2 changes: 2 additions & 0 deletions src/libipc/platform/posix/get_wait_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "libipc/utility/log.h"

namespace ipc {
namespace posix_ {
namespace detail {

inline bool calc_wait_time(timespec &ts, std::uint64_t tm /*ms*/) noexcept {
Expand All @@ -36,4 +37,5 @@ inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) {
}

} // namespace detail
} // namespace posix_
} // namespace ipc
4 changes: 2 additions & 2 deletions src/libipc/platform/posix/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class mutex {
bool lock(std::uint64_t tm) noexcept {
if (!valid()) return false;
for (;;) {
auto ts = detail::make_timespec(tm);
auto ts = posix_::detail::make_timespec(tm);
int eno = (tm == invalid_value)
? ::pthread_mutex_lock(mutex_)
: ::pthread_mutex_timedlock(mutex_, &ts);
Expand Down Expand Up @@ -230,7 +230,7 @@ class mutex {

bool try_lock() noexcept(false) {
if (!valid()) return false;
auto ts = detail::make_timespec(0);
auto ts = posix_::detail::make_timespec(0);
int eno = ::pthread_mutex_timedlock(mutex_, &ts);
switch (eno) {
case 0:
Expand Down
2 changes: 1 addition & 1 deletion src/libipc/platform/posix/semaphore_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class semaphore {
return false;
}
} else {
auto ts = detail::make_timespec(tm);
auto ts = posix_::detail::make_timespec(tm);
if (::sem_timedwait(h_, &ts) != 0) {
if (errno != ETIMEDOUT) {
ipc::error("fail sem_timedwait[%d]: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
Expand Down
Loading