Skip to content

Commit e20dd7d

Browse files
committed
add sync::mutex for windows/linux
1 parent ff488e0 commit e20dd7d

File tree

22 files changed

+622
-111
lines changed

22 files changed

+622
-111
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,4 @@ CMakeLists.txt.user*
4444

4545
# My output files
4646
build
47+
.vscode

include/libipc/def.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ using uint_t = typename uint<N>::type;
2525

2626
// constants
2727

28+
enum : std::uint32_t {
29+
invalid_value = (std::numeric_limits<std::uint32_t>::max)(),
30+
default_timeout = 100, // ms
31+
};
32+
2833
enum : std::size_t {
29-
invalid_value = (std::numeric_limits<std::size_t>::max)(),
3034
data_length = 64,
3135
large_msg_limit = data_length,
3236
large_msg_align = 512,
3337
large_msg_cache = 32,
34-
default_timeout = 100 // ms
3538
};
3639

3740
enum class relat { // multiplicity of the relationship

include/libipc/ipc.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ struct IPC_EXPORT chan_impl {
2727
static char const * name(ipc::handle_t h);
2828

2929
static std::size_t recv_count(ipc::handle_t h);
30-
static bool wait_for_recv(ipc::handle_t h, std::size_t r_count, std::size_t tm);
30+
static bool wait_for_recv(ipc::handle_t h, std::size_t r_count, std::uint64_t tm);
3131

32-
static bool send(ipc::handle_t h, void const * data, std::size_t size, std::size_t tm);
33-
static buff_t recv(ipc::handle_t h, std::size_t tm);
32+
static bool send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm);
33+
static buff_t recv(ipc::handle_t h, std::uint64_t tm);
3434

35-
static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::size_t tm);
35+
static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm);
3636
static buff_t try_recv(ipc::handle_t h);
3737
};
3838

@@ -120,41 +120,41 @@ class chan_wrapper {
120120
return detail_t::recv_count(h_);
121121
}
122122

123-
bool wait_for_recv(std::size_t r_count, std::size_t tm = invalid_value) const {
123+
bool wait_for_recv(std::size_t r_count, std::uint64_t tm = invalid_value) const {
124124
return detail_t::wait_for_recv(h_, r_count, tm);
125125
}
126126

127-
static bool wait_for_recv(char const * name, std::size_t r_count, std::size_t tm = invalid_value) {
127+
static bool wait_for_recv(char const * name, std::size_t r_count, std::uint64_t tm = invalid_value) {
128128
return chan_wrapper(name).wait_for_recv(r_count, tm);
129129
}
130130

131131
/**
132132
* If timeout, this function would call 'force_push' to send the data forcibly.
133133
*/
134-
bool send(void const * data, std::size_t size, std::size_t tm = default_timeout) {
134+
bool send(void const * data, std::size_t size, std::uint64_t tm = default_timeout) {
135135
return detail_t::send(h_, data, size, tm);
136136
}
137-
bool send(buff_t const & buff, std::size_t tm = default_timeout) {
137+
bool send(buff_t const & buff, std::uint64_t tm = default_timeout) {
138138
return this->send(buff.data(), buff.size(), tm);
139139
}
140-
bool send(std::string const & str, std::size_t tm = default_timeout) {
140+
bool send(std::string const & str, std::uint64_t tm = default_timeout) {
141141
return this->send(str.c_str(), str.size() + 1, tm);
142142
}
143143

144144
/**
145145
* If timeout, this function would just return false.
146146
*/
147-
bool try_send(void const * data, std::size_t size, std::size_t tm = default_timeout) {
147+
bool try_send(void const * data, std::size_t size, std::uint64_t tm = default_timeout) {
148148
return detail_t::try_send(h_, data, size, tm);
149149
}
150-
bool try_send(buff_t const & buff, std::size_t tm = default_timeout) {
150+
bool try_send(buff_t const & buff, std::uint64_t tm = default_timeout) {
151151
return this->try_send(buff.data(), buff.size(), tm);
152152
}
153-
bool try_send(std::string const & str, std::size_t tm = default_timeout) {
153+
bool try_send(std::string const & str, std::uint64_t tm = default_timeout) {
154154
return this->try_send(str.c_str(), str.size() + 1, tm);
155155
}
156156

157-
buff_t recv(std::size_t tm = invalid_value) {
157+
buff_t recv(std::uint64_t tm = invalid_value) {
158158
return detail_t::recv(h_, tm);
159159
}
160160

include/libipc/mutex.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
#include <cstdint> // std::uint64_t
4+
#include <system_error>
5+
6+
#include "libipc/export.h"
7+
#include "libipc/def.h"
8+
9+
namespace ipc {
10+
namespace sync {
11+
12+
class IPC_EXPORT mutex {
13+
mutex(mutex const &) = delete;
14+
mutex &operator=(mutex const &) = delete;
15+
16+
public:
17+
mutex();
18+
explicit mutex(char const *name);
19+
~mutex();
20+
21+
void const *native() const noexcept;
22+
void *native() noexcept;
23+
24+
bool valid() const noexcept;
25+
26+
bool open(char const *name) noexcept;
27+
void close() noexcept;
28+
bool lock(std::uint64_t tm = ipc::invalid_value) noexcept;
29+
bool try_lock() noexcept(false); // std::system_error
30+
bool unlock() noexcept;
31+
32+
private:
33+
class mutex_;
34+
mutex_* p_;
35+
};
36+
37+
} // namespace sync
38+
} // namespace ipc

include/libipc/shm.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include <cstddef>
4+
#include <cstdint>
45

56
#include "libipc/export.h"
67

@@ -20,6 +21,9 @@ IPC_EXPORT void release(id_t id);
2021
IPC_EXPORT void remove (id_t id);
2122
IPC_EXPORT void remove (char const * name);
2223

24+
IPC_EXPORT std::uint32_t get_ref(id_t id);
25+
IPC_EXPORT void sub_ref(id_t id);
26+
2327
class IPC_EXPORT handle {
2428
public:
2529
handle();
@@ -31,9 +35,12 @@ class IPC_EXPORT handle {
3135
void swap(handle& rhs);
3236
handle& operator=(handle rhs);
3337

34-
bool valid() const;
35-
std::size_t size () const;
36-
char const * name () const;
38+
bool valid() const noexcept;
39+
std::size_t size () const noexcept;
40+
char const * name () const noexcept;
41+
42+
std::uint32_t ref() const noexcept;
43+
void sub_ref() noexcept;
3744

3845
bool acquire(char const * name, std::size_t size, unsigned mode = create | open);
3946
void release();

include/libipc/waiter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class IPC_EXPORT semaphore {
5454
bool open (char const * name, long count = 0);
5555
void close();
5656

57-
bool wait(std::size_t tm = invalid_value);
57+
bool wait(std::uint64_t tm = invalid_value);
5858
bool post(long count = 1);
5959

6060
private:
@@ -81,7 +81,7 @@ class IPC_EXPORT condition {
8181
bool open (char const * name);
8282
void close();
8383

84-
bool wait(mutex&, std::size_t tm = invalid_value);
84+
bool wait(mutex&, std::uint64_t tm = invalid_value);
8585
bool notify();
8686
bool broadcast();
8787

src/ipc.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ struct conn_info_head {
291291
};
292292

293293
template <typename W, typename F>
294-
bool wait_for(W& waiter, F&& pred, std::size_t tm) {
294+
bool wait_for(W& waiter, F&& pred, std::uint64_t tm) {
295295
if (tm == 0) return !pred();
296296
for (unsigned k = 0; pred();) {
297297
bool loop = true, ret = true;
@@ -403,7 +403,7 @@ static std::size_t recv_count(ipc::handle_t h) noexcept {
403403
return que->conn_count();
404404
}
405405

406-
static bool wait_for_recv(ipc::handle_t h, std::size_t r_count, std::size_t tm) {
406+
static bool wait_for_recv(ipc::handle_t h, std::size_t r_count, std::uint64_t tm) {
407407
auto que = queue_of(h);
408408
if (que == nullptr) {
409409
return false;
@@ -475,7 +475,7 @@ static bool send(F&& gen_push, ipc::handle_t h, void const * data, std::size_t s
475475
return true;
476476
}
477477

478-
static bool send(ipc::handle_t h, void const * data, std::size_t size, std::size_t tm) {
478+
static bool send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
479479
return send([tm](auto info, auto que, auto msg_id) {
480480
return [tm, info, que, msg_id](std::int32_t remain, void const * data, std::size_t size) {
481481
if (!wait_for(info->wt_waiter_, [&] {
@@ -500,7 +500,7 @@ static bool send(ipc::handle_t h, void const * data, std::size_t size, std::size
500500
}, h, data, size);
501501
}
502502

503-
static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::size_t tm) {
503+
static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
504504
return send([tm](auto info, auto que, auto msg_id) {
505505
return [tm, info, que, msg_id](std::int32_t remain, void const * data, std::size_t size) {
506506
if (!wait_for(info->wt_waiter_, [&] {
@@ -514,7 +514,7 @@ static bool try_send(ipc::handle_t h, void const * data, std::size_t size, std::
514514
}, h, data, size);
515515
}
516516

517-
static ipc::buff_t recv(ipc::handle_t h, std::size_t tm) {
517+
static ipc::buff_t recv(ipc::handle_t h, std::uint64_t tm) {
518518
auto que = queue_of(h);
519519
if (que == nullptr) {
520520
ipc::error("fail: recv, queue_of(h) == nullptr\n");
@@ -630,22 +630,22 @@ std::size_t chan_impl<Flag>::recv_count(ipc::handle_t h) {
630630
}
631631

632632
template <typename Flag>
633-
bool chan_impl<Flag>::wait_for_recv(ipc::handle_t h, std::size_t r_count, std::size_t tm) {
633+
bool chan_impl<Flag>::wait_for_recv(ipc::handle_t h, std::size_t r_count, std::uint64_t tm) {
634634
return detail_impl<policy_t<Flag>>::wait_for_recv(h, r_count, tm);
635635
}
636636

637637
template <typename Flag>
638-
bool chan_impl<Flag>::send(ipc::handle_t h, void const * data, std::size_t size, std::size_t tm) {
638+
bool chan_impl<Flag>::send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
639639
return detail_impl<policy_t<Flag>>::send(h, data, size, tm);
640640
}
641641

642642
template <typename Flag>
643-
buff_t chan_impl<Flag>::recv(ipc::handle_t h, std::size_t tm) {
643+
buff_t chan_impl<Flag>::recv(ipc::handle_t h, std::uint64_t tm) {
644644
return detail_impl<policy_t<Flag>>::recv(h, tm);
645645
}
646646

647647
template <typename Flag>
648-
bool chan_impl<Flag>::try_send(ipc::handle_t h, void const * data, std::size_t size, std::size_t tm) {
648+
bool chan_impl<Flag>::try_send(ipc::handle_t h, void const * data, std::size_t size, std::uint64_t tm) {
649649
return detail_impl<policy_t<Flag>>::try_send(h, data, size, tm);
650650
}
651651

src/libipc/platform/detail.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@
2222
# error "IPC_CONSTEXPR_ has been defined."
2323
#endif
2424

25+
// detect platform
26+
27+
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || \
28+
defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \
29+
defined(WINCE) || defined(_WIN32_WCE)
30+
# define IPC_OS_WINDOWS_
31+
#endif/*WIN*/
32+
33+
#if defined(__linux__) || defined(__linux)
34+
# define IPC_OS_LINUX_
35+
#endif/*linux*/
36+
2537
#if __cplusplus >= 201703L
2638

2739
#define IPC_UNUSED_ [[maybe_unused]]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <system_error>
5+
6+
#include <sys/time.h>
7+
#include <time.h>
8+
#include <errno.h>
9+
10+
#include "libipc/utility/log.h"
11+
12+
namespace ipc {
13+
namespace detail {
14+
15+
inline bool calc_wait_time(timespec &ts, std::uint64_t tm /*ms*/) noexcept {
16+
timeval now;
17+
int eno = ::gettimeofday(&now, NULL);
18+
if (eno != 0) {
19+
ipc::error("fail gettimeofday [%d]\n", eno);
20+
return false;
21+
}
22+
ts.tv_nsec = (now.tv_usec + (tm % 1000) * 1000) * 1000;
23+
ts.tv_sec = now.tv_sec + (tm / 1000) + (ts.tv_nsec / 1000000000l);
24+
ts.tv_nsec %= 1000000000l;
25+
return true;
26+
}
27+
28+
inline timespec make_timespec(std::uint64_t tm /*ms*/) noexcept(false) {
29+
timespec ts {};
30+
if (!calc_wait_time(ts, tm)) {
31+
ipc::error("fail calc_wait_time: tm = %zd, tv_sec = %ld, tv_nsec = %ld\n",
32+
tm, ts.tv_sec, ts.tv_nsec);
33+
throw std::system_error{static_cast<int>(errno), std::system_category()};
34+
}
35+
return ts;
36+
}
37+
38+
} // namespace detail
39+
} // namespace ipc

0 commit comments

Comments
 (0)