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.
This commit is contained in:
木头云 2025-11-30 07:00:32 +00:00
parent ff74cdd57a
commit e66bd880e9
7 changed files with 11 additions and 7 deletions

View File

@ -27,7 +27,7 @@ public:
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) {

View File

@ -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 {
@ -43,4 +44,5 @@ inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) {
}
} // namespace detail
} // namespace linux
} // namespace ipc

View File

@ -25,7 +25,7 @@ public:
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}));
@ -56,7 +56,7 @@ public:
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;

View File

@ -115,7 +115,7 @@ public:
}
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) {

View File

@ -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 {
@ -36,4 +37,5 @@ inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) {
}
} // namespace detail
} // namespace posix
} // namespace ipc

View File

@ -196,7 +196,7 @@ public:
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);
@ -230,7 +230,7 @@ public:
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:

View File

@ -88,7 +88,7 @@ public:
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",