File indexing completed on 2024-05-18 08:30:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #ifndef __ZMQ_HPP_INCLUDED__
0027 #define __ZMQ_HPP_INCLUDED__
0028
0029 #ifdef _WIN32
0030 #ifndef NOMINMAX
0031 #define NOMINMAX
0032 #endif
0033 #endif
0034
0035
0036 #include <zmq.h>
0037
0038 #if defined(_MSVC_LANG)
0039 #define CPPZMQ_LANG _MSVC_LANG
0040 #else
0041 #define CPPZMQ_LANG __cplusplus
0042 #endif
0043
0044 #if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L
0045 #undef CPPZMQ_LANG
0046 #define CPPZMQ_LANG 201402L
0047 #endif
0048 #if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L
0049 #undef CPPZMQ_LANG
0050 #define CPPZMQ_LANG 201703L
0051 #endif
0052
0053
0054 #if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
0055 #define ZMQ_CPP11
0056 #endif
0057 #if CPPZMQ_LANG >= 201402L
0058 #define ZMQ_CPP14
0059 #endif
0060 #if CPPZMQ_LANG >= 201703L
0061 #define ZMQ_CPP17
0062 #endif
0063
0064 #if defined(ZMQ_CPP14) && !defined(_MSC_VER)
0065 #define ZMQ_DEPRECATED(msg) [[deprecated(msg)]]
0066 #elif defined(_MSC_VER)
0067 #define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg))
0068 #elif defined(__GNUC__)
0069 #define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
0070 #else
0071 #define ZMQ_DEPRECATED(msg)
0072 #endif
0073
0074 #if defined(ZMQ_CPP17)
0075 #define ZMQ_NODISCARD [[nodiscard]]
0076 #else
0077 #define ZMQ_NODISCARD
0078 #endif
0079
0080 #if defined(ZMQ_CPP11)
0081 #define ZMQ_NOTHROW noexcept
0082 #define ZMQ_EXPLICIT explicit
0083 #define ZMQ_OVERRIDE override
0084 #define ZMQ_NULLPTR nullptr
0085 #define ZMQ_CONSTEXPR_FN constexpr
0086 #define ZMQ_CONSTEXPR_VAR constexpr
0087 #define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
0088 #else
0089 #define ZMQ_NOTHROW throw()
0090 #define ZMQ_EXPLICIT
0091 #define ZMQ_OVERRIDE
0092 #define ZMQ_NULLPTR 0
0093 #define ZMQ_CONSTEXPR_FN
0094 #define ZMQ_CONSTEXPR_VAR const
0095 #define ZMQ_CPP11_DEPRECATED(msg)
0096 #endif
0097 #if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900) && (!defined(__GNUC__) || __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3))
0098 #define ZMQ_EXTENDED_CONSTEXPR
0099 #endif
0100 #if defined(ZMQ_CPP17)
0101 #define ZMQ_INLINE_VAR inline
0102 #define ZMQ_CONSTEXPR_IF constexpr
0103 #else
0104 #define ZMQ_INLINE_VAR
0105 #define ZMQ_CONSTEXPR_IF
0106 #endif
0107
0108 #include <cassert>
0109 #include <cstring>
0110
0111 #include <algorithm>
0112 #include <exception>
0113 #include <iomanip>
0114 #include <sstream>
0115 #include <string>
0116 #include <vector>
0117 #ifdef ZMQ_CPP11
0118 #include <array>
0119 #include <chrono>
0120 #include <tuple>
0121 #include <memory>
0122 #endif
0123
0124 #if defined(__has_include) && defined(ZMQ_CPP17)
0125 #define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
0126 #else
0127 #define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
0128 #endif
0129
0130 #if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
0131 #define CPPZMQ_HAS_OPTIONAL 1
0132 #endif
0133 #ifndef CPPZMQ_HAS_OPTIONAL
0134 #define CPPZMQ_HAS_OPTIONAL 0
0135 #elif CPPZMQ_HAS_OPTIONAL
0136 #include <optional>
0137 #endif
0138
0139 #if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
0140 #define CPPZMQ_HAS_STRING_VIEW 1
0141 #endif
0142 #ifndef CPPZMQ_HAS_STRING_VIEW
0143 #define CPPZMQ_HAS_STRING_VIEW 0
0144 #elif CPPZMQ_HAS_STRING_VIEW
0145 #include <string_view>
0146 #endif
0147
0148
0149 #define CPPZMQ_VERSION_MAJOR 4
0150 #define CPPZMQ_VERSION_MINOR 9
0151 #define CPPZMQ_VERSION_PATCH 0
0152
0153 #define CPPZMQ_VERSION \
0154 ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \
0155 CPPZMQ_VERSION_PATCH)
0156
0157
0158 #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \
0159 && defined(__GXX_EXPERIMENTAL_CXX0X__))
0160 #define ZMQ_HAS_RVALUE_REFS
0161 #define ZMQ_DELETED_FUNCTION = delete
0162 #elif defined(__clang__)
0163 #if __has_feature(cxx_rvalue_references)
0164 #define ZMQ_HAS_RVALUE_REFS
0165 #endif
0166
0167 #if __has_feature(cxx_deleted_functions)
0168 #define ZMQ_DELETED_FUNCTION = delete
0169 #else
0170 #define ZMQ_DELETED_FUNCTION
0171 #endif
0172 #elif defined(_MSC_VER) && (_MSC_VER >= 1900)
0173 #define ZMQ_HAS_RVALUE_REFS
0174 #define ZMQ_DELETED_FUNCTION = delete
0175 #elif defined(_MSC_VER) && (_MSC_VER >= 1600)
0176 #define ZMQ_HAS_RVALUE_REFS
0177 #define ZMQ_DELETED_FUNCTION
0178 #else
0179 #define ZMQ_DELETED_FUNCTION
0180 #endif
0181
0182 #if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER) \
0183 && defined(__GNUC__) && __GNUC__ < 5
0184 #define ZMQ_CPP11_PARTIAL
0185 #elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
0186
0187
0188 #define ZMQ_CPP11_PARTIAL
0189 #endif
0190
0191 #ifdef ZMQ_CPP11
0192 #ifdef ZMQ_CPP11_PARTIAL
0193 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
0194 #else
0195 #include <type_traits>
0196 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
0197 #endif
0198 #endif
0199
0200 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
0201 #define ZMQ_NEW_MONITOR_EVENT_LAYOUT
0202 #endif
0203
0204 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
0205 #define ZMQ_HAS_PROXY_STEERABLE
0206
0207 typedef struct
0208 {
0209 uint16_t event;
0210 int32_t value;
0211 } zmq_event_t;
0212 #endif
0213
0214
0215 #if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
0216 #define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
0217 #endif
0218
0219
0220
0221
0222 #ifndef NDEBUG
0223 #define ZMQ_ASSERT(expression) assert(expression)
0224 #else
0225 #define ZMQ_ASSERT(expression) (void) (expression)
0226 #endif
0227
0228 namespace zmq
0229 {
0230 #ifdef ZMQ_CPP11
0231 namespace detail
0232 {
0233 namespace ranges
0234 {
0235 using std::begin;
0236 using std::end;
0237 template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
0238 {
0239 return begin(std::forward<T>(r));
0240 }
0241 template<class T> auto end(T &&r) -> decltype(end(std::forward<T>(r)))
0242 {
0243 return end(std::forward<T>(r));
0244 }
0245 }
0246
0247 template<class T> using void_t = void;
0248
0249 template<class Iter>
0250 using iter_value_t = typename std::iterator_traits<Iter>::value_type;
0251
0252 template<class Range>
0253 using range_iter_t = decltype(
0254 ranges::begin(std::declval<typename std::remove_reference<Range>::type &>()));
0255
0256 template<class Range> using range_value_t = iter_value_t<range_iter_t<Range>>;
0257
0258 template<class T, class = void> struct is_range : std::false_type
0259 {
0260 };
0261
0262 template<class T>
0263 struct is_range<
0264 T,
0265 void_t<decltype(
0266 ranges::begin(std::declval<typename std::remove_reference<T>::type &>())
0267 == ranges::end(std::declval<typename std::remove_reference<T>::type &>()))>>
0268 : std::true_type
0269 {
0270 };
0271
0272 }
0273 #endif
0274
0275 typedef zmq_free_fn free_fn;
0276 typedef zmq_pollitem_t pollitem_t;
0277
0278
0279 #if defined _WIN32
0280 #if defined _WIN64
0281 typedef unsigned __int64 fd_t;
0282 #else
0283 typedef unsigned int fd_t;
0284 #endif
0285 #else
0286 typedef int fd_t;
0287 #endif
0288
0289 class error_t : public std::exception
0290 {
0291 public:
0292 error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
0293 explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
0294 virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
0295 {
0296 return zmq_strerror(errnum);
0297 }
0298 int num() const ZMQ_NOTHROW { return errnum; }
0299
0300 private:
0301 int errnum;
0302 };
0303
0304 namespace detail {
0305 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
0306 {
0307 int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
0308 if (rc < 0)
0309 throw error_t();
0310 return rc;
0311 }
0312 }
0313
0314 #ifdef ZMQ_CPP11
0315 ZMQ_DEPRECATED("from 4.8.0, use poll taking std::chrono::duration instead of long")
0316 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
0317 #else
0318 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1)
0319 #endif
0320 {
0321 return detail::poll(items_, nitems_, timeout_);
0322 }
0323
0324 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0325 inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1)
0326 {
0327 return detail::poll(const_cast<zmq_pollitem_t *>(items_), nitems_, timeout_);
0328 }
0329
0330 #ifdef ZMQ_CPP11
0331 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0332 inline int
0333 poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout)
0334 {
0335 return detail::poll(const_cast<zmq_pollitem_t *>(items), nitems,
0336 static_cast<long>(timeout.count()));
0337 }
0338
0339 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0340 inline int poll(std::vector<zmq_pollitem_t> const &items,
0341 std::chrono::milliseconds timeout)
0342 {
0343 return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(),
0344 static_cast<long>(timeout.count()));
0345 }
0346
0347 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
0348 inline int poll(std::vector<zmq_pollitem_t> const &items, long timeout_ = -1)
0349 {
0350 return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(), timeout_);
0351 }
0352
0353 inline int
0354 poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
0355 {
0356 return detail::poll(items, nitems, static_cast<long>(timeout.count()));
0357 }
0358
0359 inline int poll(std::vector<zmq_pollitem_t> &items,
0360 std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
0361 {
0362 return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
0363 }
0364
0365 ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono::duration instead of long")
0366 inline int poll(std::vector<zmq_pollitem_t> &items, long timeout_)
0367 {
0368 return detail::poll(items.data(), items.size(), timeout_);
0369 }
0370
0371 template<std::size_t SIZE>
0372 inline int poll(std::array<zmq_pollitem_t, SIZE> &items,
0373 std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
0374 {
0375 return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
0376 }
0377 #endif
0378
0379
0380 inline void version(int *major_, int *minor_, int *patch_)
0381 {
0382 zmq_version(major_, minor_, patch_);
0383 }
0384
0385 #ifdef ZMQ_CPP11
0386 inline std::tuple<int, int, int> version()
0387 {
0388 std::tuple<int, int, int> v;
0389 zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
0390 return v;
0391 }
0392
0393 #if !defined(ZMQ_CPP11_PARTIAL)
0394 namespace detail
0395 {
0396 template<class T> struct is_char_type
0397 {
0398
0399 static constexpr bool value =
0400 std::is_same<T, char>::value || std::is_same<T, wchar_t>::value
0401 || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value;
0402 };
0403 }
0404 #endif
0405
0406 #endif
0407
0408 class message_t
0409 {
0410 public:
0411 message_t() ZMQ_NOTHROW
0412 {
0413 int rc = zmq_msg_init(&msg);
0414 ZMQ_ASSERT(rc == 0);
0415 }
0416
0417 explicit message_t(size_t size_)
0418 {
0419 int rc = zmq_msg_init_size(&msg, size_);
0420 if (rc != 0)
0421 throw error_t();
0422 }
0423
0424 template<class ForwardIter> message_t(ForwardIter first, ForwardIter last)
0425 {
0426 typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
0427
0428 assert(std::distance(first, last) >= 0);
0429 size_t const size_ =
0430 static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
0431 int const rc = zmq_msg_init_size(&msg, size_);
0432 if (rc != 0)
0433 throw error_t();
0434 std::copy(first, last, data<value_t>());
0435 }
0436
0437 message_t(const void *data_, size_t size_)
0438 {
0439 int rc = zmq_msg_init_size(&msg, size_);
0440 if (rc != 0)
0441 throw error_t();
0442 if (size_) {
0443
0444
0445 memcpy(data(), data_, size_);
0446 }
0447 }
0448
0449 message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
0450 {
0451 int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
0452 if (rc != 0)
0453 throw error_t();
0454 }
0455
0456
0457 #if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
0458
0459
0460
0461
0462 template<
0463 class Char,
0464 size_t N,
0465 typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
0466 ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
0467 "or strings instead")
0468 explicit message_t(const Char (&data)[N]) :
0469 message_t(detail::ranges::begin(data), detail::ranges::end(data))
0470 {
0471 }
0472
0473 template<class Range,
0474 typename = typename std::enable_if<
0475 detail::is_range<Range>::value
0476 && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>)
0477 && !detail::is_char_type<detail::range_value_t<Range>>::value
0478 && !std::is_same<Range, message_t>::value>::type>
0479 explicit message_t(const Range &rng) :
0480 message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
0481 {
0482 }
0483
0484 explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
0485
0486 #if CPPZMQ_HAS_STRING_VIEW
0487 explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {}
0488 #endif
0489
0490 #endif
0491
0492 #ifdef ZMQ_HAS_RVALUE_REFS
0493 message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg)
0494 {
0495 int rc = zmq_msg_init(&rhs.msg);
0496 ZMQ_ASSERT(rc == 0);
0497 }
0498
0499 message_t &operator=(message_t &&rhs) ZMQ_NOTHROW
0500 {
0501 std::swap(msg, rhs.msg);
0502 return *this;
0503 }
0504 #endif
0505
0506 ~message_t() ZMQ_NOTHROW
0507 {
0508 int rc = zmq_msg_close(&msg);
0509 ZMQ_ASSERT(rc == 0);
0510 }
0511
0512 void rebuild()
0513 {
0514 int rc = zmq_msg_close(&msg);
0515 if (rc != 0)
0516 throw error_t();
0517 rc = zmq_msg_init(&msg);
0518 ZMQ_ASSERT(rc == 0);
0519 }
0520
0521 void rebuild(size_t size_)
0522 {
0523 int rc = zmq_msg_close(&msg);
0524 if (rc != 0)
0525 throw error_t();
0526 rc = zmq_msg_init_size(&msg, size_);
0527 if (rc != 0)
0528 throw error_t();
0529 }
0530
0531 void rebuild(const void *data_, size_t size_)
0532 {
0533 int rc = zmq_msg_close(&msg);
0534 if (rc != 0)
0535 throw error_t();
0536 rc = zmq_msg_init_size(&msg, size_);
0537 if (rc != 0)
0538 throw error_t();
0539 memcpy(data(), data_, size_);
0540 }
0541
0542 void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
0543 {
0544 int rc = zmq_msg_close(&msg);
0545 if (rc != 0)
0546 throw error_t();
0547 rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
0548 if (rc != 0)
0549 throw error_t();
0550 }
0551
0552 ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
0553 void move(message_t const *msg_)
0554 {
0555 int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
0556 if (rc != 0)
0557 throw error_t();
0558 }
0559
0560 void move(message_t &msg_)
0561 {
0562 int rc = zmq_msg_move(&msg, msg_.handle());
0563 if (rc != 0)
0564 throw error_t();
0565 }
0566
0567 ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
0568 void copy(message_t const *msg_)
0569 {
0570 int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
0571 if (rc != 0)
0572 throw error_t();
0573 }
0574
0575 void copy(message_t &msg_)
0576 {
0577 int rc = zmq_msg_copy(&msg, msg_.handle());
0578 if (rc != 0)
0579 throw error_t();
0580 }
0581
0582 bool more() const ZMQ_NOTHROW
0583 {
0584 int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
0585 return rc != 0;
0586 }
0587
0588 void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
0589
0590 const void *data() const ZMQ_NOTHROW
0591 {
0592 return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
0593 }
0594
0595 size_t size() const ZMQ_NOTHROW
0596 {
0597 return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
0598 }
0599
0600 ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
0601
0602 template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
0603
0604 template<typename T> T const *data() const ZMQ_NOTHROW
0605 {
0606 return static_cast<T const *>(data());
0607 }
0608
0609 ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
0610 bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
0611
0612 bool operator==(const message_t &other) const ZMQ_NOTHROW
0613 {
0614 const size_t my_size = size();
0615 return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
0616 }
0617
0618 bool operator!=(const message_t &other) const ZMQ_NOTHROW
0619 {
0620 return !(*this == other);
0621 }
0622
0623 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
0624 int get(int property_)
0625 {
0626 int value = zmq_msg_get(&msg, property_);
0627 if (value == -1)
0628 throw error_t();
0629 return value;
0630 }
0631 #endif
0632
0633 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
0634 const char *gets(const char *property_)
0635 {
0636 const char *value = zmq_msg_gets(&msg, property_);
0637 if (value == ZMQ_NULLPTR)
0638 throw error_t();
0639 return value;
0640 }
0641 #endif
0642
0643 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
0644 uint32_t routing_id() const
0645 {
0646 return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
0647 }
0648
0649 void set_routing_id(uint32_t routing_id)
0650 {
0651 int rc = zmq_msg_set_routing_id(&msg, routing_id);
0652 if (rc != 0)
0653 throw error_t();
0654 }
0655
0656 const char *group() const
0657 {
0658 return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
0659 }
0660
0661 void set_group(const char *group)
0662 {
0663 int rc = zmq_msg_set_group(&msg, group);
0664 if (rc != 0)
0665 throw error_t();
0666 }
0667 #endif
0668
0669
0670 std::string to_string() const
0671 {
0672 return std::string(static_cast<const char *>(data()), size());
0673 }
0674 #if CPPZMQ_HAS_STRING_VIEW
0675
0676 std::string_view to_string_view() const noexcept
0677 {
0678 return std::string_view(static_cast<const char *>(data()), size());
0679 }
0680 #endif
0681
0682
0683
0684
0685
0686
0687
0688 std::string str() const
0689 {
0690
0691 std::stringstream os;
0692
0693 const unsigned char *msg_data = this->data<unsigned char>();
0694 unsigned char byte;
0695 size_t size = this->size();
0696 int is_ascii[2] = {0, 0};
0697
0698 os << "zmq::message_t [size " << std::dec << std::setw(3)
0699 << std::setfill('0') << size << "] (";
0700
0701 if (size >= 1000) {
0702 os << "... too big to print)";
0703 } else {
0704 while (size--) {
0705 byte = *msg_data++;
0706
0707 is_ascii[1] = (byte >= 32 && byte < 127);
0708 if (is_ascii[1] != is_ascii[0])
0709 os << " ";
0710
0711 if (is_ascii[1]) {
0712 os << byte;
0713 } else {
0714 os << std::hex << std::uppercase << std::setw(2)
0715 << std::setfill('0') << static_cast<short>(byte);
0716 }
0717 is_ascii[0] = is_ascii[1];
0718 }
0719 os << ")";
0720 }
0721 return os.str();
0722 }
0723
0724 void swap(message_t &other) ZMQ_NOTHROW
0725 {
0726
0727 std::swap(msg, other.msg);
0728 }
0729
0730 ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
0731 ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; }
0732
0733 private:
0734
0735 zmq_msg_t msg;
0736
0737
0738
0739 message_t(const message_t &) ZMQ_DELETED_FUNCTION;
0740 void operator=(const message_t &) ZMQ_DELETED_FUNCTION;
0741 };
0742
0743 inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
0744 {
0745 a.swap(b);
0746 }
0747
0748 #ifdef ZMQ_CPP11
0749 enum class ctxopt
0750 {
0751 #ifdef ZMQ_BLOCKY
0752 blocky = ZMQ_BLOCKY,
0753 #endif
0754 #ifdef ZMQ_IO_THREADS
0755 io_threads = ZMQ_IO_THREADS,
0756 #endif
0757 #ifdef ZMQ_THREAD_SCHED_POLICY
0758 thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
0759 #endif
0760 #ifdef ZMQ_THREAD_PRIORITY
0761 thread_priority = ZMQ_THREAD_PRIORITY,
0762 #endif
0763 #ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
0764 thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
0765 #endif
0766 #ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
0767 thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
0768 #endif
0769 #ifdef ZMQ_THREAD_NAME_PREFIX
0770 thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
0771 #endif
0772 #ifdef ZMQ_MAX_MSGSZ
0773 max_msgsz = ZMQ_MAX_MSGSZ,
0774 #endif
0775 #ifdef ZMQ_ZERO_COPY_RECV
0776 zero_copy_recv = ZMQ_ZERO_COPY_RECV,
0777 #endif
0778 #ifdef ZMQ_MAX_SOCKETS
0779 max_sockets = ZMQ_MAX_SOCKETS,
0780 #endif
0781 #ifdef ZMQ_SOCKET_LIMIT
0782 socket_limit = ZMQ_SOCKET_LIMIT,
0783 #endif
0784 #ifdef ZMQ_IPV6
0785 ipv6 = ZMQ_IPV6,
0786 #endif
0787 #ifdef ZMQ_MSG_T_SIZE
0788 msg_t_size = ZMQ_MSG_T_SIZE
0789 #endif
0790 };
0791 #endif
0792
0793 class context_t
0794 {
0795 public:
0796 context_t()
0797 {
0798 ptr = zmq_ctx_new();
0799 if (ptr == ZMQ_NULLPTR)
0800 throw error_t();
0801 }
0802
0803
0804 explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
0805 {
0806 ptr = zmq_ctx_new();
0807 if (ptr == ZMQ_NULLPTR)
0808 throw error_t();
0809
0810 int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
0811 ZMQ_ASSERT(rc == 0);
0812
0813 rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
0814 ZMQ_ASSERT(rc == 0);
0815 }
0816
0817 #ifdef ZMQ_HAS_RVALUE_REFS
0818 context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
0819 context_t &operator=(context_t &&rhs) ZMQ_NOTHROW
0820 {
0821 close();
0822 std::swap(ptr, rhs.ptr);
0823 return *this;
0824 }
0825 #endif
0826
0827 ~context_t() ZMQ_NOTHROW { close(); }
0828
0829 ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
0830 int setctxopt(int option_, int optval_)
0831 {
0832 int rc = zmq_ctx_set(ptr, option_, optval_);
0833 ZMQ_ASSERT(rc == 0);
0834 return rc;
0835 }
0836
0837 ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
0838 int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
0839
0840 #ifdef ZMQ_CPP11
0841 void set(ctxopt option, int optval)
0842 {
0843 int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
0844 if (rc == -1)
0845 throw error_t();
0846 }
0847
0848 ZMQ_NODISCARD int get(ctxopt option)
0849 {
0850 int rc = zmq_ctx_get(ptr, static_cast<int>(option));
0851
0852
0853
0854 if (rc == -1)
0855 throw error_t();
0856 return rc;
0857 }
0858 #endif
0859
0860
0861 void close() ZMQ_NOTHROW
0862 {
0863 if (ptr == ZMQ_NULLPTR)
0864 return;
0865
0866 int rc;
0867 do {
0868 rc = zmq_ctx_term(ptr);
0869 } while (rc == -1 && errno == EINTR);
0870
0871 ZMQ_ASSERT(rc == 0);
0872 ptr = ZMQ_NULLPTR;
0873 }
0874
0875
0876
0877
0878 void shutdown() ZMQ_NOTHROW
0879 {
0880 if (ptr == ZMQ_NULLPTR)
0881 return;
0882 int rc = zmq_ctx_shutdown(ptr);
0883 ZMQ_ASSERT(rc == 0);
0884 }
0885
0886
0887
0888
0889 ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
0890
0891 ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
0892
0893 ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
0894
0895 ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
0896 operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
0897
0898 void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); }
0899
0900 private:
0901 void *ptr;
0902
0903 context_t(const context_t &) ZMQ_DELETED_FUNCTION;
0904 void operator=(const context_t &) ZMQ_DELETED_FUNCTION;
0905 };
0906
0907 inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW
0908 {
0909 a.swap(b);
0910 }
0911
0912 #ifdef ZMQ_CPP11
0913
0914 struct recv_buffer_size
0915 {
0916 size_t size;
0917 size_t untruncated_size;
0918
0919 ZMQ_NODISCARD bool truncated() const noexcept
0920 {
0921 return size != untruncated_size;
0922 }
0923 };
0924
0925 #if CPPZMQ_HAS_OPTIONAL
0926
0927 using send_result_t = std::optional<size_t>;
0928 using recv_result_t = std::optional<size_t>;
0929 using recv_buffer_result_t = std::optional<recv_buffer_size>;
0930
0931 #else
0932
0933 namespace detail
0934 {
0935
0936
0937 template<class T> class trivial_optional
0938 {
0939 public:
0940 static_assert(std::is_trivial<T>::value, "T must be trivial");
0941 using value_type = T;
0942
0943 trivial_optional() = default;
0944 trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
0945
0946 const T *operator->() const noexcept
0947 {
0948 assert(_has_value);
0949 return &_value;
0950 }
0951 T *operator->() noexcept
0952 {
0953 assert(_has_value);
0954 return &_value;
0955 }
0956
0957 const T &operator*() const noexcept
0958 {
0959 assert(_has_value);
0960 return _value;
0961 }
0962 T &operator*() noexcept
0963 {
0964 assert(_has_value);
0965 return _value;
0966 }
0967
0968 T &value()
0969 {
0970 if (!_has_value)
0971 throw std::exception();
0972 return _value;
0973 }
0974 const T &value() const
0975 {
0976 if (!_has_value)
0977 throw std::exception();
0978 return _value;
0979 }
0980
0981 explicit operator bool() const noexcept { return _has_value; }
0982 bool has_value() const noexcept { return _has_value; }
0983
0984 private:
0985 T _value{};
0986 bool _has_value{false};
0987 };
0988 }
0989
0990 using send_result_t = detail::trivial_optional<size_t>;
0991 using recv_result_t = detail::trivial_optional<size_t>;
0992 using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
0993
0994 #endif
0995
0996 namespace detail
0997 {
0998 template<class T> constexpr T enum_bit_or(T a, T b) noexcept
0999 {
1000 static_assert(std::is_enum<T>::value, "must be enum");
1001 using U = typename std::underlying_type<T>::type;
1002 return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
1003 }
1004 template<class T> constexpr T enum_bit_and(T a, T b) noexcept
1005 {
1006 static_assert(std::is_enum<T>::value, "must be enum");
1007 using U = typename std::underlying_type<T>::type;
1008 return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
1009 }
1010 template<class T> constexpr T enum_bit_xor(T a, T b) noexcept
1011 {
1012 static_assert(std::is_enum<T>::value, "must be enum");
1013 using U = typename std::underlying_type<T>::type;
1014 return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
1015 }
1016 template<class T> constexpr T enum_bit_not(T a) noexcept
1017 {
1018 static_assert(std::is_enum<T>::value, "must be enum");
1019 using U = typename std::underlying_type<T>::type;
1020 return static_cast<T>(~static_cast<U>(a));
1021 }
1022 }
1023
1024
1025 enum class send_flags : int
1026 {
1027 none = 0,
1028 dontwait = ZMQ_DONTWAIT,
1029 sndmore = ZMQ_SNDMORE
1030 };
1031
1032 constexpr send_flags operator|(send_flags a, send_flags b) noexcept
1033 {
1034 return detail::enum_bit_or(a, b);
1035 }
1036 constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1037 {
1038 return detail::enum_bit_and(a, b);
1039 }
1040 constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1041 {
1042 return detail::enum_bit_xor(a, b);
1043 }
1044 constexpr send_flags operator~(send_flags a) noexcept
1045 {
1046 return detail::enum_bit_not(a);
1047 }
1048
1049
1050 enum class recv_flags : int
1051 {
1052 none = 0,
1053 dontwait = ZMQ_DONTWAIT
1054 };
1055
1056 constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1057 {
1058 return detail::enum_bit_or(a, b);
1059 }
1060 constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1061 {
1062 return detail::enum_bit_and(a, b);
1063 }
1064 constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1065 {
1066 return detail::enum_bit_xor(a, b);
1067 }
1068 constexpr recv_flags operator~(recv_flags a) noexcept
1069 {
1070 return detail::enum_bit_not(a);
1071 }
1072
1073
1074
1075
1076
1077
1078 class mutable_buffer
1079 {
1080 public:
1081 constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
1082 constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
1083 {
1084 #ifdef ZMQ_EXTENDED_CONSTEXPR
1085 assert(p != nullptr || n == 0);
1086 #endif
1087 }
1088
1089 constexpr void *data() const noexcept { return _data; }
1090 constexpr size_t size() const noexcept { return _size; }
1091 mutable_buffer &operator+=(size_t n) noexcept
1092 {
1093
1094 const auto shift = (std::min)(n, _size);
1095 _data = static_cast<char *>(_data) + shift;
1096 _size -= shift;
1097 return *this;
1098 }
1099
1100 private:
1101 void *_data;
1102 size_t _size;
1103 };
1104
1105 inline mutable_buffer operator+(const mutable_buffer &mb, size_t n) noexcept
1106 {
1107 return mutable_buffer(static_cast<char *>(mb.data()) + (std::min)(n, mb.size()),
1108 mb.size() - (std::min)(n, mb.size()));
1109 }
1110 inline mutable_buffer operator+(size_t n, const mutable_buffer &mb) noexcept
1111 {
1112 return mb + n;
1113 }
1114
1115 class const_buffer
1116 {
1117 public:
1118 constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
1119 constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
1120 {
1121 #ifdef ZMQ_EXTENDED_CONSTEXPR
1122 assert(p != nullptr || n == 0);
1123 #endif
1124 }
1125 constexpr const_buffer(const mutable_buffer &mb) noexcept :
1126 _data(mb.data()), _size(mb.size())
1127 {
1128 }
1129
1130 constexpr const void *data() const noexcept { return _data; }
1131 constexpr size_t size() const noexcept { return _size; }
1132 const_buffer &operator+=(size_t n) noexcept
1133 {
1134 const auto shift = (std::min)(n, _size);
1135 _data = static_cast<const char *>(_data) + shift;
1136 _size -= shift;
1137 return *this;
1138 }
1139
1140 private:
1141 const void *_data;
1142 size_t _size;
1143 };
1144
1145 inline const_buffer operator+(const const_buffer &cb, size_t n) noexcept
1146 {
1147 return const_buffer(static_cast<const char *>(cb.data())
1148 + (std::min)(n, cb.size()),
1149 cb.size() - (std::min)(n, cb.size()));
1150 }
1151 inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept
1152 {
1153 return cb + n;
1154 }
1155
1156
1157
1158 constexpr mutable_buffer buffer(void *p, size_t n) noexcept
1159 {
1160 return mutable_buffer(p, n);
1161 }
1162 constexpr const_buffer buffer(const void *p, size_t n) noexcept
1163 {
1164 return const_buffer(p, n);
1165 }
1166 constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept
1167 {
1168 return mb;
1169 }
1170 inline mutable_buffer buffer(const mutable_buffer &mb, size_t n) noexcept
1171 {
1172 return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
1173 }
1174 constexpr const_buffer buffer(const const_buffer &cb) noexcept
1175 {
1176 return cb;
1177 }
1178 inline const_buffer buffer(const const_buffer &cb, size_t n) noexcept
1179 {
1180 return const_buffer(cb.data(), (std::min)(cb.size(), n));
1181 }
1182
1183 namespace detail
1184 {
1185 template<class T> struct is_buffer
1186 {
1187 static constexpr bool value =
1188 std::is_same<T, const_buffer>::value || std::is_same<T, mutable_buffer>::value;
1189 };
1190
1191 template<class T> struct is_pod_like
1192 {
1193
1194
1195
1196
1197 static constexpr bool value =
1198 ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout<T>::value;
1199 };
1200
1201 template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
1202 {
1203 return c.size();
1204 }
1205 template<class T, size_t N>
1206 constexpr size_t seq_size(const T (&)[N]) noexcept
1207 {
1208 return N;
1209 }
1210
1211 template<class Seq>
1212 auto buffer_contiguous_sequence(Seq &&seq) noexcept
1213 -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
1214 {
1215 using T = typename std::remove_cv<
1216 typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1217 static_assert(detail::is_pod_like<T>::value, "T must be POD");
1218
1219 const auto size = seq_size(seq);
1220 return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1221 size * sizeof(T));
1222 }
1223 template<class Seq>
1224 auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
1225 -> decltype(buffer_contiguous_sequence(seq))
1226 {
1227 using T = typename std::remove_cv<
1228 typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1229 static_assert(detail::is_pod_like<T>::value, "T must be POD");
1230
1231 const auto size = seq_size(seq);
1232 return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1233 (std::min)(size * sizeof(T), n_bytes));
1234 }
1235
1236 }
1237
1238
1239 template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
1240 {
1241 return detail::buffer_contiguous_sequence(data);
1242 }
1243 template<class T, size_t N>
1244 mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
1245 {
1246 return detail::buffer_contiguous_sequence(data, n_bytes);
1247 }
1248 template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
1249 {
1250 return detail::buffer_contiguous_sequence(data);
1251 }
1252 template<class T, size_t N>
1253 const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
1254 {
1255 return detail::buffer_contiguous_sequence(data, n_bytes);
1256 }
1257
1258 template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
1259 {
1260 return detail::buffer_contiguous_sequence(data);
1261 }
1262 template<class T, size_t N>
1263 mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
1264 {
1265 return detail::buffer_contiguous_sequence(data, n_bytes);
1266 }
1267 template<class T, size_t N>
1268 const_buffer buffer(std::array<const T, N> &data) noexcept
1269 {
1270 return detail::buffer_contiguous_sequence(data);
1271 }
1272 template<class T, size_t N>
1273 const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
1274 {
1275 return detail::buffer_contiguous_sequence(data, n_bytes);
1276 }
1277 template<class T, size_t N>
1278 const_buffer buffer(const std::array<T, N> &data) noexcept
1279 {
1280 return detail::buffer_contiguous_sequence(data);
1281 }
1282 template<class T, size_t N>
1283 const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
1284 {
1285 return detail::buffer_contiguous_sequence(data, n_bytes);
1286 }
1287
1288 template<class T, class Allocator>
1289 mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
1290 {
1291 return detail::buffer_contiguous_sequence(data);
1292 }
1293 template<class T, class Allocator>
1294 mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1295 {
1296 return detail::buffer_contiguous_sequence(data, n_bytes);
1297 }
1298 template<class T, class Allocator>
1299 const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
1300 {
1301 return detail::buffer_contiguous_sequence(data);
1302 }
1303 template<class T, class Allocator>
1304 const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1305 {
1306 return detail::buffer_contiguous_sequence(data, n_bytes);
1307 }
1308
1309 template<class T, class Traits, class Allocator>
1310 mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
1311 {
1312 return detail::buffer_contiguous_sequence(data);
1313 }
1314 template<class T, class Traits, class Allocator>
1315 mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
1316 size_t n_bytes) noexcept
1317 {
1318 return detail::buffer_contiguous_sequence(data, n_bytes);
1319 }
1320 template<class T, class Traits, class Allocator>
1321 const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
1322 {
1323 return detail::buffer_contiguous_sequence(data);
1324 }
1325 template<class T, class Traits, class Allocator>
1326 const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
1327 size_t n_bytes) noexcept
1328 {
1329 return detail::buffer_contiguous_sequence(data, n_bytes);
1330 }
1331
1332 #if CPPZMQ_HAS_STRING_VIEW
1333
1334 template<class T, class Traits>
1335 const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
1336 {
1337 return detail::buffer_contiguous_sequence(data);
1338 }
1339 template<class T, class Traits>
1340 const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1341 {
1342 return detail::buffer_contiguous_sequence(data, n_bytes);
1343 }
1344 #endif
1345
1346
1347
1348
1349 template<class Char, size_t N>
1350 constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept
1351 {
1352 static_assert(detail::is_pod_like<Char>::value, "Char must be POD");
1353 #ifdef ZMQ_EXTENDED_CONSTEXPR
1354 assert(data[N - 1] == Char{0});
1355 #endif
1356 return const_buffer(static_cast<const Char *>(data), (N - 1) * sizeof(Char));
1357 }
1358
1359 namespace literals
1360 {
1361 constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept
1362 {
1363 return const_buffer(str, len * sizeof(char));
1364 }
1365 constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept
1366 {
1367 return const_buffer(str, len * sizeof(wchar_t));
1368 }
1369 constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept
1370 {
1371 return const_buffer(str, len * sizeof(char16_t));
1372 }
1373 constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept
1374 {
1375 return const_buffer(str, len * sizeof(char32_t));
1376 }
1377 }
1378
1379 #ifdef ZMQ_CPP11
1380 enum class socket_type : int
1381 {
1382 req = ZMQ_REQ,
1383 rep = ZMQ_REP,
1384 dealer = ZMQ_DEALER,
1385 router = ZMQ_ROUTER,
1386 pub = ZMQ_PUB,
1387 sub = ZMQ_SUB,
1388 xpub = ZMQ_XPUB,
1389 xsub = ZMQ_XSUB,
1390 push = ZMQ_PUSH,
1391 pull = ZMQ_PULL,
1392 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
1393 server = ZMQ_SERVER,
1394 client = ZMQ_CLIENT,
1395 radio = ZMQ_RADIO,
1396 dish = ZMQ_DISH,
1397 gather = ZMQ_GATHER,
1398 scatter = ZMQ_SCATTER,
1399 dgram = ZMQ_DGRAM,
1400 #endif
1401 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
1402 peer = ZMQ_PEER,
1403 channel = ZMQ_CHANNEL,
1404 #endif
1405 #if ZMQ_VERSION_MAJOR >= 4
1406 stream = ZMQ_STREAM,
1407 #endif
1408 pair = ZMQ_PAIR
1409 };
1410 #endif
1411
1412 namespace sockopt
1413 {
1414
1415
1416
1417
1418
1419 template<int Opt, class T, bool BoolUnit = false> struct integral_option
1420 {
1421 };
1422
1423
1424
1425
1426
1427 template<int Opt, int NullTerm = 1> struct array_option
1428 {
1429 };
1430
1431 #define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \
1432 using NAME##_t = integral_option<OPT, TYPE, false>; \
1433 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1434 #define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \
1435 using NAME##_t = integral_option<OPT, TYPE, true>; \
1436 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1437 #define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \
1438 using NAME##_t = array_option<OPT>; \
1439 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1440 #define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \
1441 using NAME##_t = array_option<OPT, 0>; \
1442 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1443 #define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \
1444 using NAME##_t = array_option<OPT, 2>; \
1445 ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1446
1447
1448 using cppzmq_fd_t = ::zmq::fd_t;
1449
1450 #ifdef ZMQ_AFFINITY
1451 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1452 #endif
1453 #ifdef ZMQ_BACKLOG
1454 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1455 #endif
1456 #ifdef ZMQ_BINDTODEVICE
1457 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1458 #endif
1459 #ifdef ZMQ_CONFLATE
1460 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1461 #endif
1462 #ifdef ZMQ_CONNECT_ROUTING_ID
1463 ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1464 #endif
1465 #ifdef ZMQ_CONNECT_TIMEOUT
1466 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1467 #endif
1468 #ifdef ZMQ_CURVE_PUBLICKEY
1469 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1470 #endif
1471 #ifdef ZMQ_CURVE_SECRETKEY
1472 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1473 #endif
1474 #ifdef ZMQ_CURVE_SERVER
1475 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1476 #endif
1477 #ifdef ZMQ_CURVE_SERVERKEY
1478 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1479 #endif
1480 #ifdef ZMQ_EVENTS
1481 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1482 #endif
1483 #ifdef ZMQ_FD
1484 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, ::zmq::fd_t);
1485 #endif
1486 #ifdef ZMQ_GSSAPI_PLAINTEXT
1487 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1488 #endif
1489 #ifdef ZMQ_GSSAPI_SERVER
1490 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1491 #endif
1492 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1493 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1494 #endif
1495 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1496 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1497 gssapi_service_principal_nametype,
1498 int);
1499 #endif
1500 #ifdef ZMQ_GSSAPI_PRINCIPAL
1501 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1502 #endif
1503 #ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1504 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
1505 gssapi_principal_nametype,
1506 int);
1507 #endif
1508 #ifdef ZMQ_HANDSHAKE_IVL
1509 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1510 #endif
1511 #ifdef ZMQ_HEARTBEAT_IVL
1512 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1513 #endif
1514 #ifdef ZMQ_HEARTBEAT_TIMEOUT
1515 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1516 #endif
1517 #ifdef ZMQ_HEARTBEAT_TTL
1518 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1519 #endif
1520 #ifdef ZMQ_IMMEDIATE
1521 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1522 #endif
1523 #ifdef ZMQ_INVERT_MATCHING
1524 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1525 #endif
1526 #ifdef ZMQ_IPV6
1527 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1528 #endif
1529 #ifdef ZMQ_LAST_ENDPOINT
1530 ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1531 #endif
1532 #ifdef ZMQ_LINGER
1533 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1534 #endif
1535 #ifdef ZMQ_MAXMSGSIZE
1536 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1537 #endif
1538 #ifdef ZMQ_MECHANISM
1539 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1540 #endif
1541 #ifdef ZMQ_METADATA
1542 ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1543 #endif
1544 #ifdef ZMQ_MULTICAST_HOPS
1545 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1546 #endif
1547 #ifdef ZMQ_MULTICAST_LOOP
1548 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1549 #endif
1550 #ifdef ZMQ_MULTICAST_MAXTPDU
1551 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1552 #endif
1553 #ifdef ZMQ_ONLY_FIRST_SUBSCRIBE
1554 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ONLY_FIRST_SUBSCRIBE, only_first_subscribe, int);
1555 #endif
1556 #ifdef ZMQ_PLAIN_SERVER
1557 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1558 #endif
1559 #ifdef ZMQ_PLAIN_PASSWORD
1560 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1561 #endif
1562 #ifdef ZMQ_PLAIN_USERNAME
1563 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1564 #endif
1565 #ifdef ZMQ_USE_FD
1566 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1567 #endif
1568 #ifdef ZMQ_PROBE_ROUTER
1569 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1570 #endif
1571 #ifdef ZMQ_RATE
1572 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1573 #endif
1574 #ifdef ZMQ_RCVBUF
1575 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1576 #endif
1577 #ifdef ZMQ_RCVHWM
1578 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1579 #endif
1580 #ifdef ZMQ_RCVMORE
1581 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1582 #endif
1583 #ifdef ZMQ_RCVTIMEO
1584 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1585 #endif
1586 #ifdef ZMQ_RECONNECT_IVL
1587 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1588 #endif
1589 #ifdef ZMQ_RECONNECT_IVL_MAX
1590 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1591 #endif
1592 #ifdef ZMQ_RECOVERY_IVL
1593 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1594 #endif
1595 #ifdef ZMQ_REQ_CORRELATE
1596 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1597 #endif
1598 #ifdef ZMQ_REQ_RELAXED
1599 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1600 #endif
1601 #ifdef ZMQ_ROUTER_HANDOVER
1602 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1603 #endif
1604 #ifdef ZMQ_ROUTER_MANDATORY
1605 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1606 #endif
1607 #ifdef ZMQ_ROUTER_NOTIFY
1608 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1609 #endif
1610 #ifdef ZMQ_ROUTING_ID
1611 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1612 #endif
1613 #ifdef ZMQ_SNDBUF
1614 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1615 #endif
1616 #ifdef ZMQ_SNDHWM
1617 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1618 #endif
1619 #ifdef ZMQ_SNDTIMEO
1620 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1621 #endif
1622 #ifdef ZMQ_SOCKS_PROXY
1623 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1624 #endif
1625 #ifdef ZMQ_STREAM_NOTIFY
1626 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1627 #endif
1628 #ifdef ZMQ_SUBSCRIBE
1629 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1630 #endif
1631 #ifdef ZMQ_TCP_KEEPALIVE
1632 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1633 #endif
1634 #ifdef ZMQ_TCP_KEEPALIVE_CNT
1635 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1636 #endif
1637 #ifdef ZMQ_TCP_KEEPALIVE_IDLE
1638 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1639 #endif
1640 #ifdef ZMQ_TCP_KEEPALIVE_INTVL
1641 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1642 #endif
1643 #ifdef ZMQ_TCP_MAXRT
1644 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1645 #endif
1646 #ifdef ZMQ_THREAD_SAFE
1647 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1648 #endif
1649 #ifdef ZMQ_TOS
1650 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1651 #endif
1652 #ifdef ZMQ_TYPE
1653 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1654 #ifdef ZMQ_CPP11
1655 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, socket_type, socket_type);
1656 #endif
1657 #endif
1658 #ifdef ZMQ_UNSUBSCRIBE
1659 ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1660 #endif
1661 #ifdef ZMQ_VMCI_BUFFER_SIZE
1662 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1663 #endif
1664 #ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1665 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1666 #endif
1667 #ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1668 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1669 #endif
1670 #ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1671 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1672 #endif
1673 #ifdef ZMQ_XPUB_VERBOSE
1674 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1675 #endif
1676 #ifdef ZMQ_XPUB_VERBOSER
1677 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1678 #endif
1679 #ifdef ZMQ_XPUB_MANUAL
1680 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1681 #endif
1682 #ifdef ZMQ_XPUB_NODROP
1683 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1684 #endif
1685 #ifdef ZMQ_XPUB_WELCOME_MSG
1686 ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1687 #endif
1688 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1689 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1690 #endif
1691 #ifdef ZMQ_ZAP_DOMAIN
1692 ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1693 #endif
1694
1695 }
1696 #endif
1697
1698
1699 namespace detail
1700 {
1701 class socket_base
1702 {
1703 public:
1704 socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {}
1705 ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
1706
1707 template<typename T>
1708 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1709 void setsockopt(int option_, T const &optval)
1710 {
1711 setsockopt(option_, &optval, sizeof(T));
1712 }
1713
1714 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1715 void setsockopt(int option_, const void *optval_, size_t optvallen_)
1716 {
1717 int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1718 if (rc != 0)
1719 throw error_t();
1720 }
1721
1722 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1723 void getsockopt(int option_, void *optval_, size_t *optvallen_) const
1724 {
1725 int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1726 if (rc != 0)
1727 throw error_t();
1728 }
1729
1730 template<typename T>
1731 ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1732 T getsockopt(int option_) const
1733 {
1734 T optval;
1735 size_t optlen = sizeof(T);
1736 getsockopt(option_, &optval, &optlen);
1737 return optval;
1738 }
1739
1740 #ifdef ZMQ_CPP11
1741
1742
1743 template<int Opt, class T, bool BoolUnit>
1744 void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
1745 {
1746 static_assert(std::is_integral<T>::value, "T must be integral");
1747 set_option(Opt, &val, sizeof val);
1748 }
1749
1750
1751
1752 template<int Opt, class T>
1753 void set(sockopt::integral_option<Opt, T, true>, bool val)
1754 {
1755 static_assert(std::is_integral<T>::value, "T must be integral");
1756 T rep_val = val;
1757 set_option(Opt, &rep_val, sizeof rep_val);
1758 }
1759
1760
1761
1762 template<int Opt, int NullTerm>
1763 void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
1764 {
1765 set_option(Opt, buf, std::strlen(buf));
1766 }
1767
1768
1769
1770 template<int Opt, int NullTerm>
1771 void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
1772 {
1773 set_option(Opt, buf.data(), buf.size());
1774 }
1775
1776
1777
1778 template<int Opt, int NullTerm>
1779 void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
1780 {
1781 set_option(Opt, buf.data(), buf.size());
1782 }
1783
1784 #if CPPZMQ_HAS_STRING_VIEW
1785
1786
1787 template<int Opt, int NullTerm>
1788 void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1789 {
1790 set_option(Opt, buf.data(), buf.size());
1791 }
1792 #endif
1793
1794
1795
1796 template<int Opt, class T, bool BoolUnit>
1797 ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
1798 {
1799 static_assert(std::is_scalar<T>::value, "T must be scalar");
1800 T val;
1801 size_t size = sizeof val;
1802 get_option(Opt, &val, &size);
1803 assert(size == sizeof val);
1804 return val;
1805 }
1806
1807
1808
1809 template<int Opt, int NullTerm>
1810 ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
1811 mutable_buffer buf) const
1812 {
1813 size_t size = buf.size();
1814 get_option(Opt, buf.data(), &size);
1815 return size;
1816 }
1817
1818
1819
1820
1821
1822 template<int Opt, int NullTerm>
1823 ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
1824 size_t init_size = 1024) const
1825 {
1826 if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1827 if (init_size == 1024) {
1828 init_size = 41;
1829 }
1830 }
1831 std::string str(init_size, '\0');
1832 size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
1833 if ZMQ_CONSTEXPR_IF (NullTerm == 1) {
1834 if (size > 0) {
1835 assert(str[size - 1] == '\0');
1836 --size;
1837 }
1838 } else if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1839 assert(size == 32 || size == 41);
1840 if (size == 41) {
1841 assert(str[size - 1] == '\0');
1842 --size;
1843 }
1844 }
1845 str.resize(size);
1846 return str;
1847 }
1848 #endif
1849
1850 void bind(std::string const &addr) { bind(addr.c_str()); }
1851
1852 void bind(const char *addr_)
1853 {
1854 int rc = zmq_bind(_handle, addr_);
1855 if (rc != 0)
1856 throw error_t();
1857 }
1858
1859 void unbind(std::string const &addr) { unbind(addr.c_str()); }
1860
1861 void unbind(const char *addr_)
1862 {
1863 int rc = zmq_unbind(_handle, addr_);
1864 if (rc != 0)
1865 throw error_t();
1866 }
1867
1868 void connect(std::string const &addr) { connect(addr.c_str()); }
1869
1870 void connect(const char *addr_)
1871 {
1872 int rc = zmq_connect(_handle, addr_);
1873 if (rc != 0)
1874 throw error_t();
1875 }
1876
1877 void disconnect(std::string const &addr) { disconnect(addr.c_str()); }
1878
1879 void disconnect(const char *addr_)
1880 {
1881 int rc = zmq_disconnect(_handle, addr_);
1882 if (rc != 0)
1883 throw error_t();
1884 }
1885
1886 ZMQ_DEPRECATED("from 4.7.1, use handle() != nullptr or operator bool")
1887 bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); }
1888
1889 ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
1890 size_t send(const void *buf_, size_t len_, int flags_ = 0)
1891 {
1892 int nbytes = zmq_send(_handle, buf_, len_, flags_);
1893 if (nbytes >= 0)
1894 return static_cast<size_t>(nbytes);
1895 if (zmq_errno() == EAGAIN)
1896 return 0;
1897 throw error_t();
1898 }
1899
1900 ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1901 bool send(message_t &msg_,
1902 int flags_ = 0)
1903 {
1904 int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1905 if (nbytes >= 0)
1906 return true;
1907 if (zmq_errno() == EAGAIN)
1908 return false;
1909 throw error_t();
1910 }
1911
1912 template<typename T>
1913 ZMQ_CPP11_DEPRECATED(
1914 "from 4.4.1, use send taking message_t or buffer (for contiguous "
1915 "ranges), and send_flags")
1916 bool send(T first, T last, int flags_ = 0)
1917 {
1918 zmq::message_t msg(first, last);
1919 int nbytes = zmq_msg_send(msg.handle(), _handle, flags_);
1920 if (nbytes >= 0)
1921 return true;
1922 if (zmq_errno() == EAGAIN)
1923 return false;
1924 throw error_t();
1925 }
1926
1927 #ifdef ZMQ_HAS_RVALUE_REFS
1928 ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1929 bool send(message_t &&msg_,
1930 int flags_ = 0)
1931 {
1932 #ifdef ZMQ_CPP11
1933 return send(msg_, static_cast<send_flags>(flags_)).has_value();
1934 #else
1935 return send(msg_, flags_);
1936 #endif
1937 }
1938 #endif
1939
1940 #ifdef ZMQ_CPP11
1941 send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
1942 {
1943 const int nbytes =
1944 zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1945 if (nbytes >= 0)
1946 return static_cast<size_t>(nbytes);
1947 if (zmq_errno() == EAGAIN)
1948 return {};
1949 throw error_t();
1950 }
1951
1952 send_result_t send(message_t &msg, send_flags flags)
1953 {
1954 int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
1955 if (nbytes >= 0)
1956 return static_cast<size_t>(nbytes);
1957 if (zmq_errno() == EAGAIN)
1958 return {};
1959 throw error_t();
1960 }
1961
1962 send_result_t send(message_t &&msg, send_flags flags)
1963 {
1964 return send(msg, flags);
1965 }
1966 #endif
1967
1968 ZMQ_CPP11_DEPRECATED(
1969 "from 4.3.1, use recv taking a mutable_buffer and recv_flags")
1970 size_t recv(void *buf_, size_t len_, int flags_ = 0)
1971 {
1972 int nbytes = zmq_recv(_handle, buf_, len_, flags_);
1973 if (nbytes >= 0)
1974 return static_cast<size_t>(nbytes);
1975 if (zmq_errno() == EAGAIN)
1976 return 0;
1977 throw error_t();
1978 }
1979
1980 ZMQ_CPP11_DEPRECATED(
1981 "from 4.3.1, use recv taking a reference to message_t and recv_flags")
1982 bool recv(message_t *msg_, int flags_ = 0)
1983 {
1984 int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
1985 if (nbytes >= 0)
1986 return true;
1987 if (zmq_errno() == EAGAIN)
1988 return false;
1989 throw error_t();
1990 }
1991
1992 #ifdef ZMQ_CPP11
1993 ZMQ_NODISCARD
1994 recv_buffer_result_t recv(mutable_buffer buf,
1995 recv_flags flags = recv_flags::none)
1996 {
1997 const int nbytes =
1998 zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1999 if (nbytes >= 0) {
2000 return recv_buffer_size{
2001 (std::min)(static_cast<size_t>(nbytes), buf.size()),
2002 static_cast<size_t>(nbytes)};
2003 }
2004 if (zmq_errno() == EAGAIN)
2005 return {};
2006 throw error_t();
2007 }
2008
2009 ZMQ_NODISCARD
2010 recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
2011 {
2012 const int nbytes =
2013 zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
2014 if (nbytes >= 0) {
2015 assert(msg.size() == static_cast<size_t>(nbytes));
2016 return static_cast<size_t>(nbytes);
2017 }
2018 if (zmq_errno() == EAGAIN)
2019 return {};
2020 throw error_t();
2021 }
2022 #endif
2023
2024 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2025 void join(const char *group)
2026 {
2027 int rc = zmq_join(_handle, group);
2028 if (rc != 0)
2029 throw error_t();
2030 }
2031
2032 void leave(const char *group)
2033 {
2034 int rc = zmq_leave(_handle, group);
2035 if (rc != 0)
2036 throw error_t();
2037 }
2038 #endif
2039
2040 ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; }
2041 ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; }
2042
2043 ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2044
2045
2046 ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
2047
2048 protected:
2049 void *_handle;
2050
2051 private:
2052 void set_option(int option_, const void *optval_, size_t optvallen_)
2053 {
2054 int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
2055 if (rc != 0)
2056 throw error_t();
2057 }
2058
2059 void get_option(int option_, void *optval_, size_t *optvallen_) const
2060 {
2061 int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
2062 if (rc != 0)
2063 throw error_t();
2064 }
2065 };
2066 }
2067
2068 struct from_handle_t
2069 {
2070 struct _private
2071 {
2072 };
2073 ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private ) ZMQ_NOTHROW {}
2074 };
2075
2076 ZMQ_CONSTEXPR_VAR from_handle_t from_handle =
2077 from_handle_t(from_handle_t::_private());
2078
2079
2080
2081 class socket_ref : public detail::socket_base
2082 {
2083 public:
2084 socket_ref() ZMQ_NOTHROW : detail::socket_base() {}
2085 #ifdef ZMQ_CPP11
2086 socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
2087 #endif
2088 socket_ref(from_handle_t , void *handle) ZMQ_NOTHROW
2089 : detail::socket_base(handle)
2090 {
2091 }
2092 };
2093
2094 #ifdef ZMQ_CPP11
2095 inline bool operator==(socket_ref sr, std::nullptr_t ) ZMQ_NOTHROW
2096 {
2097 return sr.handle() == nullptr;
2098 }
2099 inline bool operator==(std::nullptr_t , socket_ref sr) ZMQ_NOTHROW
2100 {
2101 return sr.handle() == nullptr;
2102 }
2103 inline bool operator!=(socket_ref sr, std::nullptr_t ) ZMQ_NOTHROW
2104 {
2105 return !(sr == nullptr);
2106 }
2107 inline bool operator!=(std::nullptr_t , socket_ref sr) ZMQ_NOTHROW
2108 {
2109 return !(sr == nullptr);
2110 }
2111 #endif
2112
2113 inline bool operator==(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2114 {
2115 return std::equal_to<const void *>()(a.handle(), b.handle());
2116 }
2117 inline bool operator!=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2118 {
2119 return !(a == b);
2120 }
2121 inline bool operator<(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2122 {
2123 return std::less<const void *>()(a.handle(), b.handle());
2124 }
2125 inline bool operator>(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2126 {
2127 return b < a;
2128 }
2129 inline bool operator<=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2130 {
2131 return !(a > b);
2132 }
2133 inline bool operator>=(const detail::socket_base& a, const detail::socket_base& b) ZMQ_NOTHROW
2134 {
2135 return !(a < b);
2136 }
2137
2138 }
2139
2140 #ifdef ZMQ_CPP11
2141 namespace std
2142 {
2143 template<> struct hash<zmq::socket_ref>
2144 {
2145 size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
2146 {
2147 return hash<void *>()(sr.handle());
2148 }
2149 };
2150 }
2151 #endif
2152
2153 namespace zmq
2154 {
2155 class socket_t : public detail::socket_base
2156 {
2157 friend class monitor_t;
2158
2159 public:
2160 socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {}
2161
2162 socket_t(context_t &context_, int type_) :
2163 detail::socket_base(zmq_socket(context_.handle(), type_)),
2164 ctxptr(context_.handle())
2165 {
2166 if (_handle == ZMQ_NULLPTR)
2167 throw error_t();
2168 }
2169
2170 #ifdef ZMQ_CPP11
2171 socket_t(context_t &context_, socket_type type_) :
2172 socket_t(context_, static_cast<int>(type_))
2173 {
2174 }
2175 #endif
2176
2177 #ifdef ZMQ_HAS_RVALUE_REFS
2178 socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
2179 ctxptr(rhs.ctxptr)
2180 {
2181 rhs._handle = ZMQ_NULLPTR;
2182 rhs.ctxptr = ZMQ_NULLPTR;
2183 }
2184 socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW
2185 {
2186 close();
2187 std::swap(_handle, rhs._handle);
2188 std::swap(ctxptr, rhs.ctxptr);
2189 return *this;
2190 }
2191 #endif
2192
2193 ~socket_t() ZMQ_NOTHROW { close(); }
2194
2195 operator void *() ZMQ_NOTHROW { return _handle; }
2196
2197 operator void const *() const ZMQ_NOTHROW { return _handle; }
2198
2199 void close() ZMQ_NOTHROW
2200 {
2201 if (_handle == ZMQ_NULLPTR)
2202
2203 return;
2204 int rc = zmq_close(_handle);
2205 ZMQ_ASSERT(rc == 0);
2206 _handle = ZMQ_NULLPTR;
2207 ctxptr = ZMQ_NULLPTR;
2208 }
2209
2210 void swap(socket_t &other) ZMQ_NOTHROW
2211 {
2212 std::swap(_handle, other._handle);
2213 std::swap(ctxptr, other.ctxptr);
2214 }
2215
2216 operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); }
2217
2218 private:
2219 void *ctxptr;
2220
2221 socket_t(const socket_t &) ZMQ_DELETED_FUNCTION;
2222 void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2223
2224
2225 socket_t(void *context_, int type_) :
2226 detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
2227 {
2228 if (_handle == ZMQ_NULLPTR)
2229 throw error_t();
2230 if (ctxptr == ZMQ_NULLPTR)
2231 throw error_t();
2232 }
2233 };
2234
2235 inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW
2236 {
2237 a.swap(b);
2238 }
2239
2240 ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
2241 inline void proxy(void *frontend, void *backend, void *capture)
2242 {
2243 int rc = zmq_proxy(frontend, backend, capture);
2244 if (rc != 0)
2245 throw error_t();
2246 }
2247
2248 inline void
2249 proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref())
2250 {
2251 int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
2252 if (rc != 0)
2253 throw error_t();
2254 }
2255
2256 #ifdef ZMQ_HAS_PROXY_STEERABLE
2257 ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2258 inline void
2259 proxy_steerable(void *frontend, void *backend, void *capture, void *control)
2260 {
2261 int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2262 if (rc != 0)
2263 throw error_t();
2264 }
2265
2266 inline void proxy_steerable(socket_ref frontend,
2267 socket_ref backend,
2268 socket_ref capture,
2269 socket_ref control)
2270 {
2271 int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(),
2272 capture.handle(), control.handle());
2273 if (rc != 0)
2274 throw error_t();
2275 }
2276 #endif
2277
2278 class monitor_t
2279 {
2280 public:
2281 monitor_t() : _socket(), _monitor_socket() {}
2282
2283 virtual ~monitor_t() { close(); }
2284
2285 #ifdef ZMQ_HAS_RVALUE_REFS
2286 monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket()
2287 {
2288 std::swap(_socket, rhs._socket);
2289 std::swap(_monitor_socket, rhs._monitor_socket);
2290 }
2291
2292 monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW
2293 {
2294 close();
2295 _socket = socket_ref();
2296 std::swap(_socket, rhs._socket);
2297 std::swap(_monitor_socket, rhs._monitor_socket);
2298 return *this;
2299 }
2300 #endif
2301
2302
2303 void
2304 monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2305 {
2306 monitor(socket, addr.c_str(), events);
2307 }
2308
2309 void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2310 {
2311 init(socket, addr_, events);
2312 while (true) {
2313 check_event(-1);
2314 }
2315 }
2316
2317 void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2318 {
2319 init(socket, addr.c_str(), events);
2320 }
2321
2322 void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2323 {
2324 int rc = zmq_socket_monitor(socket.handle(), addr_, events);
2325 if (rc != 0)
2326 throw error_t();
2327
2328 _socket = socket;
2329 _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
2330 _monitor_socket.connect(addr_);
2331
2332 on_monitor_started();
2333 }
2334
2335 bool check_event(int timeout = 0)
2336 {
2337 assert(_monitor_socket);
2338
2339 zmq::message_t eventMsg;
2340
2341 zmq::pollitem_t items[] = {
2342 {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0},
2343 };
2344
2345 #ifdef ZMQ_CPP11
2346 zmq::poll(&items[0], 1, std::chrono::milliseconds(timeout));
2347 #else
2348 zmq::poll(&items[0], 1, timeout);
2349 #endif
2350
2351 if (items[0].revents & ZMQ_POLLIN) {
2352 int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0);
2353 if (rc == -1 && zmq_errno() == ETERM)
2354 return false;
2355 assert(rc != -1);
2356
2357 } else {
2358 return false;
2359 }
2360
2361 #if ZMQ_VERSION_MAJOR >= 4
2362 const char *data = static_cast<const char *>(eventMsg.data());
2363 zmq_event_t msgEvent;
2364 memcpy(&msgEvent.event, data, sizeof(uint16_t));
2365 data += sizeof(uint16_t);
2366 memcpy(&msgEvent.value, data, sizeof(int32_t));
2367 zmq_event_t *event = &msgEvent;
2368 #else
2369 zmq_event_t *event = static_cast<zmq_event_t *>(eventMsg.data());
2370 #endif
2371
2372 #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2373 zmq::message_t addrMsg;
2374 int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0);
2375 if (rc == -1 && zmq_errno() == ETERM) {
2376 return false;
2377 }
2378
2379 assert(rc != -1);
2380 std::string address = addrMsg.to_string();
2381 #else
2382
2383 std::string address = event->data.connected.addr;
2384 #endif
2385
2386 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2387 if (event->event == ZMQ_EVENT_MONITOR_STOPPED) {
2388 return false;
2389 }
2390
2391 #endif
2392
2393 switch (event->event) {
2394 case ZMQ_EVENT_CONNECTED:
2395 on_event_connected(*event, address.c_str());
2396 break;
2397 case ZMQ_EVENT_CONNECT_DELAYED:
2398 on_event_connect_delayed(*event, address.c_str());
2399 break;
2400 case ZMQ_EVENT_CONNECT_RETRIED:
2401 on_event_connect_retried(*event, address.c_str());
2402 break;
2403 case ZMQ_EVENT_LISTENING:
2404 on_event_listening(*event, address.c_str());
2405 break;
2406 case ZMQ_EVENT_BIND_FAILED:
2407 on_event_bind_failed(*event, address.c_str());
2408 break;
2409 case ZMQ_EVENT_ACCEPTED:
2410 on_event_accepted(*event, address.c_str());
2411 break;
2412 case ZMQ_EVENT_ACCEPT_FAILED:
2413 on_event_accept_failed(*event, address.c_str());
2414 break;
2415 case ZMQ_EVENT_CLOSED:
2416 on_event_closed(*event, address.c_str());
2417 break;
2418 case ZMQ_EVENT_CLOSE_FAILED:
2419 on_event_close_failed(*event, address.c_str());
2420 break;
2421 case ZMQ_EVENT_DISCONNECTED:
2422 on_event_disconnected(*event, address.c_str());
2423 break;
2424 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0) || (defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3))
2425 case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
2426 on_event_handshake_failed_no_detail(*event, address.c_str());
2427 break;
2428 case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
2429 on_event_handshake_failed_protocol(*event, address.c_str());
2430 break;
2431 case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
2432 on_event_handshake_failed_auth(*event, address.c_str());
2433 break;
2434 case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
2435 on_event_handshake_succeeded(*event, address.c_str());
2436 break;
2437 #elif defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2438 case ZMQ_EVENT_HANDSHAKE_FAILED:
2439 on_event_handshake_failed(*event, address.c_str());
2440 break;
2441 case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2442 on_event_handshake_succeed(*event, address.c_str());
2443 break;
2444 #endif
2445 default:
2446 on_event_unknown(*event, address.c_str());
2447 break;
2448 }
2449
2450 return true;
2451 }
2452
2453 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2454 void abort()
2455 {
2456 if (_socket)
2457 zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2458
2459 _socket = socket_ref();
2460 }
2461 #endif
2462 virtual void on_monitor_started() {}
2463 virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
2464 {
2465 (void) event_;
2466 (void) addr_;
2467 }
2468 virtual void on_event_connect_delayed(const zmq_event_t &event_,
2469 const char *addr_)
2470 {
2471 (void) event_;
2472 (void) addr_;
2473 }
2474 virtual void on_event_connect_retried(const zmq_event_t &event_,
2475 const char *addr_)
2476 {
2477 (void) event_;
2478 (void) addr_;
2479 }
2480 virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
2481 {
2482 (void) event_;
2483 (void) addr_;
2484 }
2485 virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
2486 {
2487 (void) event_;
2488 (void) addr_;
2489 }
2490 virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
2491 {
2492 (void) event_;
2493 (void) addr_;
2494 }
2495 virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
2496 {
2497 (void) event_;
2498 (void) addr_;
2499 }
2500 virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
2501 {
2502 (void) event_;
2503 (void) addr_;
2504 }
2505 virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
2506 {
2507 (void) event_;
2508 (void) addr_;
2509 }
2510 virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
2511 {
2512 (void) event_;
2513 (void) addr_;
2514 }
2515 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2516 virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_,
2517 const char *addr_)
2518 {
2519 (void) event_;
2520 (void) addr_;
2521 }
2522 virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_,
2523 const char *addr_)
2524 {
2525 (void) event_;
2526 (void) addr_;
2527 }
2528 virtual void on_event_handshake_failed_auth(const zmq_event_t &event_,
2529 const char *addr_)
2530 {
2531 (void) event_;
2532 (void) addr_;
2533 }
2534 virtual void on_event_handshake_succeeded(const zmq_event_t &event_,
2535 const char *addr_)
2536 {
2537 (void) event_;
2538 (void) addr_;
2539 }
2540 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2541 virtual void on_event_handshake_failed(const zmq_event_t &event_,
2542 const char *addr_)
2543 {
2544 (void) event_;
2545 (void) addr_;
2546 }
2547 virtual void on_event_handshake_succeed(const zmq_event_t &event_,
2548 const char *addr_)
2549 {
2550 (void) event_;
2551 (void) addr_;
2552 }
2553 #endif
2554 virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
2555 {
2556 (void) event_;
2557 (void) addr_;
2558 }
2559
2560 private:
2561 monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION;
2562 void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION;
2563
2564 socket_ref _socket;
2565 socket_t _monitor_socket;
2566
2567 void close() ZMQ_NOTHROW
2568 {
2569 if (_socket)
2570 zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2571 _monitor_socket.close();
2572 }
2573 };
2574
2575 #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2576
2577
2578 enum class event_flags : short
2579 {
2580 none = 0,
2581 pollin = ZMQ_POLLIN,
2582 pollout = ZMQ_POLLOUT,
2583 pollerr = ZMQ_POLLERR,
2584 pollpri = ZMQ_POLLPRI
2585 };
2586
2587 constexpr event_flags operator|(event_flags a, event_flags b) noexcept
2588 {
2589 return detail::enum_bit_or(a, b);
2590 }
2591 constexpr event_flags operator&(event_flags a, event_flags b) noexcept
2592 {
2593 return detail::enum_bit_and(a, b);
2594 }
2595 constexpr event_flags operator^(event_flags a, event_flags b) noexcept
2596 {
2597 return detail::enum_bit_xor(a, b);
2598 }
2599 constexpr event_flags operator~(event_flags a) noexcept
2600 {
2601 return detail::enum_bit_not(a);
2602 }
2603
2604 struct no_user_data;
2605
2606
2607 template<class T = no_user_data> struct poller_event
2608 {
2609 socket_ref socket;
2610 ::zmq::fd_t fd;
2611 T *user_data;
2612 event_flags events;
2613 };
2614
2615 template<typename T = no_user_data> class poller_t
2616 {
2617 public:
2618 using event_type = poller_event<T>;
2619
2620 poller_t() : poller_ptr(zmq_poller_new())
2621 {
2622 if (!poller_ptr)
2623 throw error_t();
2624 }
2625
2626 template<
2627 typename Dummy = void,
2628 typename =
2629 typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
2630 void add(zmq::socket_ref socket, event_flags events, T *user_data)
2631 {
2632 add_impl(socket, events, user_data);
2633 }
2634
2635 void add(zmq::socket_ref socket, event_flags events)
2636 {
2637 add_impl(socket, events, nullptr);
2638 }
2639
2640 void remove(zmq::socket_ref socket)
2641 {
2642 if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) {
2643 throw error_t();
2644 }
2645 }
2646
2647 void modify(zmq::socket_ref socket, event_flags events)
2648 {
2649 if (0
2650 != zmq_poller_modify(poller_ptr.get(), socket.handle(),
2651 static_cast<short>(events))) {
2652 throw error_t();
2653 }
2654 }
2655
2656 size_t wait_all(std::vector<event_type> &poller_events,
2657 const std::chrono::milliseconds timeout)
2658 {
2659 int rc = zmq_poller_wait_all(
2660 poller_ptr.get(),
2661 reinterpret_cast<zmq_poller_event_t *>(poller_events.data()),
2662 static_cast<int>(poller_events.size()),
2663 static_cast<long>(timeout.count()));
2664 if (rc > 0)
2665 return static_cast<size_t>(rc);
2666
2667 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2668 if (zmq_errno() == EAGAIN)
2669 #else
2670 if (zmq_errno() == ETIMEDOUT)
2671 #endif
2672 return 0;
2673
2674 throw error_t();
2675 }
2676
2677 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
2678 size_t size() const noexcept
2679 {
2680 int rc = zmq_poller_size(const_cast<void *>(poller_ptr.get()));
2681 ZMQ_ASSERT(rc >= 0);
2682 return static_cast<size_t>(std::max(rc, 0));
2683 }
2684 #endif
2685
2686 private:
2687 struct destroy_poller_t
2688 {
2689 void operator()(void *ptr) noexcept
2690 {
2691 int rc = zmq_poller_destroy(&ptr);
2692 ZMQ_ASSERT(rc == 0);
2693 }
2694 };
2695
2696 std::unique_ptr<void, destroy_poller_t> poller_ptr;
2697
2698 void add_impl(zmq::socket_ref socket, event_flags events, T *user_data)
2699 {
2700 if (0
2701 != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
2702 static_cast<short>(events))) {
2703 throw error_t();
2704 }
2705 }
2706 };
2707 #endif
2708
2709 inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
2710 {
2711 return os << msg.str();
2712 }
2713
2714 }
2715
2716 #endif