- 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
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.
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.
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'