Skip to content

Commit 83b91c8

Browse files
committed
Problem: Missing swap functions
Solution: Implement for socket_t, context_t, message_t and poller_t Additionally remove dependency on <functional> by refactoring poller_t and remove unused <unordered_map> include.
1 parent e1fe5e5 commit 83b91c8

File tree

7 files changed

+108
-9
lines changed

7 files changed

+108
-9
lines changed

tests/context.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
#include <catch.hpp>
22
#include <zmq.hpp>
33

4+
#if (__cplusplus >= 201703L)
5+
static_assert(std::is_nothrow_swappable<zmq::context_t>::value,
6+
"context_t should be nothrow swappable");
7+
#endif
8+
49
TEST_CASE("context construct default and destroy", "[context]")
510
{
611
zmq::context_t context;
@@ -12,3 +17,13 @@ TEST_CASE("context create, close and destroy", "[context]")
1217
context.close();
1318
CHECK(NULL == (void *) context);
1419
}
20+
21+
#ifdef ZMQ_CPP11
22+
TEST_CASE("context swap", "[context]")
23+
{
24+
zmq::context_t context1;
25+
zmq::context_t context2;
26+
using std::swap;
27+
swap(context1, context2);
28+
}
29+
#endif

tests/message.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,33 @@ static_assert(!std::is_copy_constructible<zmq::message_t>::value,
88
static_assert(!std::is_copy_assignable<zmq::message_t>::value,
99
"message_t should not be copy-assignable");
1010
#endif
11+
#if (__cplusplus >= 201703L)
12+
static_assert(std::is_nothrow_swappable<zmq::message_t>::value,
13+
"message_t should be nothrow swappable");
14+
#endif
1115

1216
TEST_CASE("message default constructed", "[message]")
1317
{
1418
const zmq::message_t message;
1519
CHECK(0u == message.size());
1620
}
1721

22+
#ifdef ZMQ_CPP11
23+
TEST_CASE("message swap", "[message]")
24+
{
25+
const std::string data = "foo";
26+
zmq::message_t message1;
27+
zmq::message_t message2(data.data(), data.size());
28+
using std::swap;
29+
swap(message1, message2);
30+
CHECK(message1.size() == data.size());
31+
CHECK(message2.size() == 0);
32+
swap(message1, message2);
33+
CHECK(message1.size() == 0);
34+
CHECK(message2.size() == data.size());
35+
}
36+
#endif
37+
1838
namespace {
1939
const char *const data = "Hi";
2040
}

tests/monitor.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <thread>
55
#include <mutex>
66
#include <condition_variable>
7+
#include <functional>
78

89
class mock_monitor_t : public zmq::monitor_t
910
{

tests/poller.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
#include <array>
66
#include <memory>
77

8+
#if (__cplusplus >= 201703L)
9+
static_assert(std::is_nothrow_swappable<zmq::poller_t<>>::value,
10+
"poller_t should be nothrow swappable");
11+
#endif
12+
813
TEST_CASE("poller create destroy", "[poller]")
914
{
1015
zmq::poller_t<> poller;
@@ -28,6 +33,14 @@ TEST_CASE("poller move assign empty", "[poller]")
2833
b = std::move(a);
2934
}
3035

36+
TEST_CASE("poller swap", "[poller]")
37+
{
38+
zmq::poller_t<> a;
39+
zmq::poller_t<> b;
40+
using std::swap;
41+
swap(a, b);
42+
}
43+
3144
TEST_CASE("poller move construct non empty", "[poller]")
3245
{
3346
zmq::context_t context;

tests/socket.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
#include <future>
55
#endif
66

7+
#if (__cplusplus >= 201703L)
8+
static_assert(std::is_nothrow_swappable<zmq::socket_t>::value,
9+
"socket_t should be nothrow swappable");
10+
#endif
11+
712
TEST_CASE("socket create destroy", "[socket]")
813
{
914
zmq::context_t context;
@@ -16,6 +21,15 @@ TEST_CASE("socket create by enum and destroy", "[socket]")
1621
zmq::context_t context;
1722
zmq::socket_t socket(context, zmq::socket_type::router);
1823
}
24+
25+
TEST_CASE("socket swap", "[socket]")
26+
{
27+
zmq::context_t context;
28+
zmq::socket_t socket1(context, zmq::socket_type::router);
29+
zmq::socket_t socket2(context, zmq::socket_type::dealer);
30+
using std::swap;
31+
swap(socket1, socket2);
32+
}
1933
#endif
2034

2135
TEST_CASE("socket sends and receives const buffer", "[socket]")

zmq.hpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@
7373
#ifdef ZMQ_CPP11
7474
#include <chrono>
7575
#include <tuple>
76-
#include <functional>
77-
#include <unordered_map>
7876
#include <memory>
7977
#endif
8078

@@ -476,6 +474,12 @@ class message_t
476474
return os.str();
477475
}
478476

477+
void swap(message_t &other) ZMQ_NOTHROW
478+
{
479+
// this assumes zmq::msg_t from libzmq is trivially relocatable
480+
std::swap(msg, other.msg);
481+
}
482+
479483
private:
480484
// The underlying message
481485
zmq_msg_t msg;
@@ -486,6 +490,11 @@ class message_t
486490
void operator=(const message_t &) ZMQ_DELETED_FUNCTION;
487491
};
488492

493+
inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
494+
{
495+
a.swap(b);
496+
}
497+
489498
class context_t
490499
{
491500
public:
@@ -554,13 +563,22 @@ class context_t
554563

555564
operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
556565

566+
void swap(context_t &other) ZMQ_NOTHROW
567+
{
568+
std::swap(ptr, other.ptr);
569+
}
570+
557571
private:
558572
void *ptr;
559573

560574
context_t(const context_t &) ZMQ_DELETED_FUNCTION;
561575
void operator=(const context_t &) ZMQ_DELETED_FUNCTION;
562576
};
563577

578+
inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW {
579+
a.swap(b);
580+
}
581+
564582
#ifdef ZMQ_CPP11
565583
enum class socket_type : int
566584
{
@@ -767,6 +785,12 @@ class socket_t
767785
}
768786
#endif
769787

788+
void swap(socket_t &other) ZMQ_NOTHROW
789+
{
790+
std::swap(ptr, other.ptr);
791+
std::swap(ctxptr, other.ctxptr);
792+
}
793+
770794
private:
771795
void *ptr;
772796
void *ctxptr;
@@ -775,6 +799,10 @@ class socket_t
775799
void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
776800
};
777801

802+
inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW {
803+
a.swap(b);
804+
}
805+
778806
ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
779807
inline void proxy(void *frontend, void *backend, void *capture)
780808
{
@@ -1119,6 +1147,8 @@ class monitor_t
11191147
template<typename T = void> class poller_t
11201148
{
11211149
public:
1150+
poller_t() = default;
1151+
11221152
void add(zmq::socket_t &socket, short events, T *user_data)
11231153
{
11241154
if (0
@@ -1164,17 +1194,19 @@ template<typename T = void> class poller_t
11641194
}
11651195

11661196
private:
1167-
std::unique_ptr<void, std::function<void(void *)>> poller_ptr{
1197+
std::unique_ptr<void, void(*)(void *)> poller_ptr{
11681198
[]() {
11691199
auto poller_new = zmq_poller_new();
11701200
if (poller_new)
11711201
return poller_new;
11721202
throw error_t();
1173-
}(),
1174-
[](void *ptr) {
1175-
int rc = zmq_poller_destroy(&ptr);
1176-
ZMQ_ASSERT(rc == 0);
1177-
}};
1203+
}(), &destroy_poller};
1204+
1205+
static void destroy_poller(void *ptr)
1206+
{
1207+
int rc = zmq_poller_destroy(&ptr);
1208+
ZMQ_ASSERT(rc == 0);
1209+
}
11781210
};
11791211
#endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
11801212

zmq_addon.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
#include <iomanip>
3131
#include <sstream>
3232
#include <stdexcept>
33+
#ifdef ZMQ_CPP11
34+
#include <functional>
35+
#include <unordered_map>
36+
#endif
3337

3438
namespace zmq
3539
{
@@ -245,7 +249,7 @@ class multipart_t
245249
m_parts.pop_back();
246250
return message;
247251
}
248-
252+
249253
// get message part from front
250254
const message_t &front()
251255
{

0 commit comments

Comments
 (0)