657 Commits

Author SHA1 Message Date
mutouyun
7eb7b93bfa Replace custom hash struct with std::hash in unordered_map definition 2025-12-03 08:13:44 +00:00
mutouyun
9d6bb92a15 Fix the issue caused by inconsistent lifecycle of the global IPC object. 2025-12-03 08:13:44 +00:00
mutouyun
a1f858f560 Refactoring the generic memory allocator 2025-12-03 08:13:44 +00:00
mutouyun
10c0d14de6 Reimplement the allocator required for the container type with $new 2025-12-03 08:13:44 +00:00
mutouyun
4e70d6c60b Use $new instead of alloc 2025-12-03 08:13:44 +00:00
mutouyun
5db7e70cdd Simplify the implementation of memory allocation management 2025-12-03 08:13:00 +00:00
mutouyun
8b384ba5f2 The memory allocator supports runtime dynamic size memory allocation 2025-12-03 08:13:00 +00:00
mutouyun
ef9d3b3642 libipc/memory/resource.h => libipc/mem/resource.h 2025-12-03 08:13:00 +00:00
mutouyun
e3c1755b9a Add $new 2025-12-03 08:11:57 +00:00
mutouyun
0b33859d33 Add block_pool 2025-12-03 08:11:57 +00:00
mutouyun
dd8307e81a Adjust the allocator name 2025-12-03 08:11:57 +00:00
mutouyun
823fda9ea1 Simplify verify_args function to fix error C3249 2025-12-03 08:11:57 +00:00
mutouyun
6fcb40d117 Fix fmt function to handle null pointers and return empty string 2025-12-03 08:11:57 +00:00
木头云
d0bd85a2c0 Update c-cpp.yml 2025-12-03 08:11:57 +00:00
mutouyun
a2da0621e8 Fix fmt function to handle empty strings and update make_prefix template parameters 2025-12-03 08:11:57 +00:00
mutouyun
e7a8005f58 Optimize memory_resource & add monotonic_buffer_resource 2025-12-03 08:11:57 +00:00
mutouyun
e83bd8f874 Add intrusive_stack 2025-12-03 08:11:57 +00:00
mutouyun
d260897b16 Add allocator and rewrite allocator_wrapper 2025-12-03 08:11:57 +00:00
mutouyun
976610f914 Optimized partial implementation using fmt 2025-12-03 08:11:57 +00:00
mutouyun
a4361d2b97 Start refactoring memory management, adding memory_resource 2025-12-03 08:11:57 +00:00
mutouyun
73ce564ab2 Update platform-specific feature macros to new interfaces in imp 2025-12-03 08:11:57 +00:00
mutouyun
b70dea04c5 Add system 2025-12-03 08:11:24 +00:00
mutouyun
453f964bdd Add result 2025-12-03 08:11:24 +00:00
mutouyun
09a304161f IPC_EXPORT => LIBIPC_EXPORT 2025-12-03 08:11:24 +00:00
mutouyun
1fd07a2dec Add log 2025-12-03 08:08:03 +00:00
mutouyun
4c1f829c06 Add error 2025-12-03 08:08:03 +00:00
mutouyun
e7b6fcd79d Added fmt support for byte 2025-12-03 08:08:03 +00:00
mutouyun
7e7bfb8467 Add fmt 2025-12-03 08:08:03 +00:00
mutouyun
e717ad46fb Add codecvt 2025-12-03 08:08:03 +00:00
mutouyun
7f73c24019 libimp => libipc 2025-12-03 08:08:03 +00:00
mutouyun
b3d520cd25 Add nameof & scope_exit 2025-12-03 08:08:03 +00:00
mutouyun
f987e35870 Move the export.h file to the imp directory 2025-12-03 08:08:03 +00:00
mutouyun
6387385fc0 Add expected 2025-12-03 08:08:03 +00:00
mutouyun
8098c8e37a Add imp for subsequent refactoring 2025-12-03 08:08:03 +00:00
木头云
f8e71a548c
Merge pull request #159 from mutouyun/refactoring-ut
refactor(test): comprehensive unit test refactoring
2025-11-30 19:36:52 +08:00
木头云
cf5738eb3a fix(test): replace C++17 structured bindings with C++14 compatible code
Problem:
- Two test cases in test_buffer.cpp used structured bindings (auto [a, b])
- Structured bindings are a C++17 feature
- Project requires C++14 compatibility

Solution:
- Replace 'auto [ptr, size] = buf.to_tuple()' with C++14 compatible code
- Use std::get<N>() to extract tuple elements
- Modified tests: ToTupleNonConst, ToTupleConst

Changes:
- Line 239: Use std::get<0/1>(tuple) instead of structured binding
- Line 252: Use std::get<0/1>(tuple) instead of structured binding
- Add explanatory comments for clarity

This ensures the test suite compiles with C++14 standard.
2025-11-30 11:16:03 +00:00
木头云
c31ef988c1 fix(shm): remove redundant self-assignment in shm_win.cpp
- Remove useless 'ii->size_ = ii->size_;' statement at line 140
- The user-requested size is already set in acquire() function
- Simplify else branch to just a comment for clarity
- No functional change, just code cleanup
2025-11-30 11:06:04 +00:00
木头云
7726742157 feat(shm): implement reference counting for Windows shared memory
Problem:
- Reference counting tests fail on Windows (ReleaseMemory, ReferenceCount,
  SubtractReference, HandleRef, HandleSubRef)
- get_ref() and sub_ref() were stub implementations returning 0/doing nothing
- CreateFileMapping HANDLE lacks built-in reference counting mechanism

Solution:
- Implement reference counting using std::atomic<std::int32_t> stored at
  the end of shared memory (same strategy as POSIX version)
- Add calc_size() helper to allocate extra space for atomic counter
- Add acc_of() helper to access the atomic counter at the end of memory
- Modify acquire() to allocate calc_size(size) instead of size
- Modify get_mem() to initialize counter to 1 on first mapping
- Modify release() to decrement counter and return ref count before decrement
- Implement get_ref() to return current reference count
- Implement sub_ref() to atomically decrement reference count
- Convert file from Windows (CRLF) to Unix (LF) line endings for consistency

Key Implementation Details:
1. Reference counter stored at end of shared memory (aligned to info_t)
2. First get_mem() call: fetch_add(1) initializes counter to 1
3. release() returns ref count before decrement (for semantics compatibility)
4. Memory layout: [user data][padding][atomic<int32_t> counter]
5. Uses memory_order_acquire/release/acq_rel for proper synchronization

This makes Windows implementation match POSIX behavior and ensures all
reference counting tests pass on Windows platform.
2025-11-30 10:55:24 +00:00
木头云
b9dd75ccd9 fix(platform): rename linux/posix namespaces to avoid predefined macro conflict
Problem:
- 'linux' is a predefined macro on Linux platforms
- Using 'namespace linux' causes compilation errors
- Preprocessor replaces 'linux' with '1' before compilation

Solution:
- Rename 'namespace linux' to 'namespace linux_'
- Rename 'namespace posix' to 'namespace posix_'
- Update all 7 call sites accordingly:
  - linux/condition.h:  linux_::detail::make_timespec()
  - linux/mutex.h:      linux_::detail::make_timespec() (2 places)
  - posix/condition.h:  posix_::detail::make_timespec()
  - posix/mutex.h:      posix_::detail::make_timespec() (2 places)
  - posix/semaphore_impl.h: posix_::detail::make_timespec()

This prevents preprocessor macro expansion issues while maintaining
the ODR violation fix from the previous commit.
2025-11-30 07:07:14 +00:00
木头云
e66bd880e9 fix(platform): resolve ODR violation in make_timespec/calc_wait_time inline functions
Problem:
- Both linux/get_wait_time.h and posix/get_wait_time.h define inline functions
  make_timespec() and calc_wait_time() in namespace ipc::detail
- On Linux, semaphore uses posix implementation, but may include both headers
- This causes ODR (One Definition Rule) violation - undefined behavior
- Different inline function definitions with same name violates C++ standard
- Manifested as test failures in SemaphoreTest::WaitTimeout

Solution:
- Add platform-specific namespace layer between ipc and detail:
  - linux/get_wait_time.h: ipc::linux::detail::make_timespec()
  - posix/get_wait_time.h: ipc::posix::detail::make_timespec()
- Update all call sites to use fully qualified names:
  - linux/condition.h: linux::detail::make_timespec()
  - linux/mutex.h: linux::detail::make_timespec() (2 places)
  - posix/condition.h: posix::detail::make_timespec()
  - posix/mutex.h: posix::detail::make_timespec() (2 places)
  - posix/semaphore_impl.h: posix::detail::make_timespec()

This ensures each platform's implementation is uniquely named, preventing
ODR violations and ensuring correct function resolution at compile time.
2025-11-30 07:00:32 +00:00
木头云
ff74cdd57a fix(test): correct receiver loop count in MultipleSendersReceivers
Problem:
- Receivers were exiting after receiving only messages_per_sender (5) messages
- In broadcast mode, each message is sent to ALL receivers
- If sender1 completes quickly, all receivers get 5 messages and exit
- This causes sender2's messages to fail (no active receivers)

Solution:
- Each receiver should loop for num_senders * messages_per_sender (2 * 5 = 10) messages
- This ensures all receivers stay active until ALL senders complete
- Now receivers wait for: 2 senders × 5 messages each = 10 total messages
- Expected received_count: 2 senders × 5 messages × 2 receivers = 20 messages

This fix ensures all senders can successfully complete their sends before
any receiver exits.
2025-11-30 06:38:38 +00:00
木头云
78be284668 fix(test): correct test logic and semantics in multiple test cases
1. ChannelTest::MultipleSendersReceivers
   - Add C++14-compatible latch implementation (similar to C++20 std::latch)
   - Ensure receivers are ready before senders start sending messages
   - This prevents race condition where senders might send before receivers are listening

2. RWLockTest::ReadWriteReadPattern
   - Fix test logic: lock_shared allows multiple concurrent readers
   - Previous test had race condition where both threads could read same value
   - New test: each thread writes based on thread id (1 or 2), then reads
   - Expected result: 1*20 + 2*20 = 60

3. ShmTest::ReleaseMemory
   - Correct return value semantics: release() returns ref count before decrement, or -1 on error
   - Must call get_mem() to map memory and set ref count to 1 before release
   - Expected: release() returns 1 (ref count before decrement)

4. ShmTest::ReferenceCount
   - Correct semantics: ref count is 0 after acquire (memory not mapped)
   - get_mem() maps memory and sets ref count to 1
   - Second acquire+get_mem increases ref count to 2
   - Test now properly validates reference counting behavior

5. ShmTest::SubtractReference
   - sub_ref() only works after get_mem() has mapped the memory
   - Must call get_mem() first to initialize ref count to 1
   - sub_ref() then decrements it to 0
   - Test now follows correct API usage pattern
2025-11-30 06:06:54 +00:00
木头云
d5f787596a fix(test): fix double-free in HandleDetachAttach test
- Problem: calling h2.release() followed by shm::remove(id) causes use-after-free
  - h2.release() internally calls shm::release(id) which frees the id structure
  - shm::remove(id) then accesses the freed id pointer -> crash

- Solution: detach the id from handle first, then call shm::remove(id)
  - h2.detach() returns the id without releasing it
  - shm::remove(id) can then safely clean up both memory and disk file

- This completes the fix for all ShmTest double-free issues
2025-11-30 05:38:59 +00:00
木头云
0ecf1a4137 docs(shm): add semantic comments for release/remove and fix double-free in tests
- Add comprehensive documentation for shm::release(id), shm::remove(id), and shm::remove(name)
  - release(id): Decrements ref count, cleans up memory and disk file when count reaches zero
  - remove(id): Calls release(id) internally, then forces disk file cleanup (WARNING: do not use after release)
  - remove(name): Only removes disk file, safe to use anytime

- Fix critical double-free bug in ShmTest test cases
  - Problem: calling release(id) followed by remove(id) causes use-after-free crash
    because release() already frees the id structure
  - Solution: replace 'release(id); remove(id);' pattern with just 'remove(id)'
  - Fixed tests: AcquireCreate, AcquireCreateOrOpen, GetMemory, GetMemoryNoSize,
    RemoveById, SubtractReference
  - Kept 'release(id); remove(name);' pattern unchanged (safe usage)

- Add explanatory comments in test code to prevent future misuse
2025-11-30 05:28:48 +00:00
木头云
91e4489a55 refactor(buffer): rename 'additional' parameter to 'mem_to_free' for clarity
Header changes (include/libipc/buffer.h):
- Rename: additional → mem_to_free (better semantic name)
- Add documentation comments explaining the parameter's purpose
- Clarifies that mem_to_free is passed to destructor instead of p
- Use case: when data pointer is offset into a larger allocation

Implementation changes (src/libipc/buffer.cpp):
- Update parameter name in constructor implementation
- No logic changes, just naming improvement

Test changes (test/test_buffer.cpp):
- Fix TEST_F(BufferTest, ConstructorWithMemToFree)
- Previous test caused crash: passed stack variable address to destructor
- New test correctly demonstrates the parameter's purpose:
  * Allocate 100-byte block
  * Use offset portion (bytes 25-75) as data
  * Destructor receives original block pointer for proper cleanup
- Prevents double-free and invalid free errors

Semantic explanation:
  buffer(data_ptr, size, destructor, mem_to_free)

  On destruction:
    destructor(mem_to_free ? mem_to_free : data_ptr, size)

  This allows:
    char* block = new char[100];
    char* data = block + 25;
    buffer buf(data, 50, my_free, block);  // Frees 'block', not 'data'
2025-11-30 05:09:56 +00:00
木头云
de76cf80d5 fix(buffer): remove const from char constructor to prevent UB
- Change: explicit buffer(char const & c) → explicit buffer(char & c)
- Remove dangerous const_cast in implementation
- Before: buffer(const_cast<char*>(&c), 1) [UB if c is truly const]
- After: buffer(&c, 1) [safe, requires non-const char]
- Prevents undefined behavior from modifying compile-time constants
- Constructor now correctly requires mutable char reference
- Aligns with buffer's mutable data semantics

The previous implementation with const_cast could lead to:
- Modifying string literals (undefined behavior)
- Modifying const variables (undefined behavior)
- Runtime crashes or data corruption

Example of prevented misuse:
  buffer buf('X');           // Now: compile error ✓
  char c = 'X';
  buffer buf(c);             // Now: works correctly ✓
  const char cc = 'Y';
  buffer buf(cc);            // Now: compile error ✓
2025-11-30 05:00:57 +00:00
木头云
8103c117f1 fix(buffer): remove redundant const qualifier in array constructor
- Change: byte_t const (& data)[N] → byte_t (& data)[N]
- Allows non-const byte arrays to be accepted by the constructor
- Fixes defect discovered by TEST_F(BufferTest, ConstructorFromByteArray)
- The const qualifier on array elements was too restrictive
- Keep char const & c unchanged as it's correct for single char reference
2025-11-30 04:56:02 +00:00
木头云
7447a86d41 fix(test): correct member vs non-member function calls in test_shm.cpp
- Fix handle class member functions: remove incorrect shm:: prefix
  - h.acquire() not h.shm::acquire()
  - h.release() not h.shm::release()
  - h.sub_ref() not h.shm::sub_ref()
- Keep shm:: prefix for namespace-level global functions:
  - shm::acquire(), shm::release(id), shm::get_mem()
  - shm::remove(), shm::get_ref(id), shm::sub_ref(id)
- Fix comments to use correct terminology
- Resolves: 'shm::acquire is not a class member' compilation errors
2025-11-30 04:50:21 +00:00
木头云
7092df53bb fix(test): resolve id_t ambiguity in test_shm.cpp
- Remove 'using namespace ipc::shm;' to avoid id_t conflict with system id_t
- Add explicit shm:: namespace prefix to all shm types and functions
- Apply to: id_t, handle, acquire, get_mem, release, remove, get_ref, sub_ref
- Apply to: create and open constants
- Fix comments to avoid incorrect namespace references
- Resolves compilation error: 'reference to id_t is ambiguous'
2025-11-30 04:29:55 +00:00
木头云
2cde78d692 style(test): change indentation from 4 spaces to 2 spaces
- Update all test files to use 2-space indentation
- Affects: test_buffer.cpp, test_shm.cpp, test_mutex.cpp
- Affects: test_semaphore.cpp, test_condition.cpp
- Affects: test_locks.cpp, test_ipc_channel.cpp
- Improves code consistency and readability
2025-11-30 04:22:24 +00:00