3rdparty/cppzmq/zmq.hpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2016-2017 ZeroMQ community
3  Copyright (c) 2009-2011 250bpm s.r.o.
4  Copyright (c) 2011 Botond Ballo
5  Copyright (c) 2007-2009 iMatix Corporation
6 
7  Permission is hereby granted, free of charge, to any person obtaining a copy
8  of this software and associated documentation files (the "Software"), to
9  deal in the Software without restriction, including without limitation the
10  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11  sell copies of the Software, and to permit persons to whom the Software is
12  furnished to do so, subject to the following conditions:
13 
14  The above copyright notice and this permission notice shall be included in
15  all copies or substantial portions of the Software.
16 
17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23  IN THE SOFTWARE.
24 */
25 
26 #ifndef __ZMQ_HPP_INCLUDED__
27 #define __ZMQ_HPP_INCLUDED__
28 
29 #ifdef _WIN32
30 #ifndef NOMINMAX
31 #define NOMINMAX
32 #endif
33 #endif
34 
35 // included here for _HAS_CXX* macros
36 #include <zmq.h>
37 
38 #if defined(_MSVC_LANG)
39 #define CPPZMQ_LANG _MSVC_LANG
40 #else
41 #define CPPZMQ_LANG __cplusplus
42 #endif
43 // overwrite if specific language macros indicate higher version
44 #if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L
45 #undef CPPZMQ_LANG
46 #define CPPZMQ_LANG 201402L
47 #endif
48 #if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L
49 #undef CPPZMQ_LANG
50 #define CPPZMQ_LANG 201703L
51 #endif
52 
53 // macros defined if has a specific standard or greater
54 #if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
55 #define ZMQ_CPP11
56 #endif
57 #if CPPZMQ_LANG >= 201402L
58 #define ZMQ_CPP14
59 #endif
60 #if CPPZMQ_LANG >= 201703L
61 #define ZMQ_CPP17
62 #endif
63 
64 #if defined(ZMQ_CPP14) && !defined(_MSC_VER)
65 #define ZMQ_DEPRECATED(msg) [[deprecated(msg)]]
66 #elif defined(_MSC_VER)
67 #define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg))
68 #elif defined(__GNUC__)
69 #define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
70 #endif
71 
72 #if defined(ZMQ_CPP17)
73 #define ZMQ_NODISCARD [[nodiscard]]
74 #else
75 #define ZMQ_NODISCARD
76 #endif
77 
78 #if defined(ZMQ_CPP11)
79 #define ZMQ_NOTHROW noexcept
80 #define ZMQ_EXPLICIT explicit
81 #define ZMQ_OVERRIDE override
82 #define ZMQ_NULLPTR nullptr
83 #define ZMQ_CONSTEXPR_FN constexpr
84 #define ZMQ_CONSTEXPR_VAR constexpr
85 #define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
86 #else
87 #define ZMQ_NOTHROW throw()
88 #define ZMQ_EXPLICIT
89 #define ZMQ_OVERRIDE
90 #define ZMQ_NULLPTR 0
91 #define ZMQ_CONSTEXPR_FN
92 #define ZMQ_CONSTEXPR_VAR const
93 #define ZMQ_CPP11_DEPRECATED(msg)
94 #endif
95 #if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900)
96 #define ZMQ_EXTENDED_CONSTEXPR
97 #endif
98 #if defined(ZMQ_CPP17)
99 #define ZMQ_INLINE_VAR inline
100 #define ZMQ_CONSTEXPR_IF constexpr
101 #else
102 #define ZMQ_INLINE_VAR
103 #define ZMQ_CONSTEXPR_IF
104 #endif
105 
106 #include <cassert>
107 #include <cstring>
108 
109 #include <algorithm>
110 #include <exception>
111 #include <iomanip>
112 #include <sstream>
113 #include <string>
114 #include <vector>
115 #ifdef ZMQ_CPP11
116 #include <array>
117 #include <chrono>
118 #include <tuple>
119 #include <memory>
120 #endif
121 
122 #if defined(__has_include) && defined(ZMQ_CPP17)
123 #define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
124 #else
125 #define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
126 #endif
127 
128 #if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
129 #define CPPZMQ_HAS_OPTIONAL 1
130 #endif
131 #ifndef CPPZMQ_HAS_OPTIONAL
132 #define CPPZMQ_HAS_OPTIONAL 0
133 #elif CPPZMQ_HAS_OPTIONAL
134 #include <optional>
135 #endif
136 
137 #if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
138 #define CPPZMQ_HAS_STRING_VIEW 1
139 #endif
140 #ifndef CPPZMQ_HAS_STRING_VIEW
141 #define CPPZMQ_HAS_STRING_VIEW 0
142 #elif CPPZMQ_HAS_STRING_VIEW
143 #include <string_view>
144 #endif
145 
146 /* Version macros for compile-time API version detection */
147 #define CPPZMQ_VERSION_MAJOR 4
148 #define CPPZMQ_VERSION_MINOR 8
149 #define CPPZMQ_VERSION_PATCH 0
150 
151 #define CPPZMQ_VERSION \
152  ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \
153  CPPZMQ_VERSION_PATCH)
154 
155 // Detect whether the compiler supports C++11 rvalue references.
156 #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \
157  && defined(__GXX_EXPERIMENTAL_CXX0X__))
158 #define ZMQ_HAS_RVALUE_REFS
159 #define ZMQ_DELETED_FUNCTION = delete
160 #elif defined(__clang__)
161 #if __has_feature(cxx_rvalue_references)
162 #define ZMQ_HAS_RVALUE_REFS
163 #endif
164 
165 #if __has_feature(cxx_deleted_functions)
166 #define ZMQ_DELETED_FUNCTION = delete
167 #else
168 #define ZMQ_DELETED_FUNCTION
169 #endif
170 #elif defined(_MSC_VER) && (_MSC_VER >= 1900)
171 #define ZMQ_HAS_RVALUE_REFS
172 #define ZMQ_DELETED_FUNCTION = delete
173 #elif defined(_MSC_VER) && (_MSC_VER >= 1600)
174 #define ZMQ_HAS_RVALUE_REFS
175 #define ZMQ_DELETED_FUNCTION
176 #else
177 #define ZMQ_DELETED_FUNCTION
178 #endif
179 
180 #if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER) \
181  && defined(__GNUC__) && __GNUC__ < 5
182 #define ZMQ_CPP11_PARTIAL
183 #elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
184 //the date here is the last date of gcc 4.9.4, which
185 // effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch
186 #define ZMQ_CPP11_PARTIAL
187 #endif
188 
189 #ifdef ZMQ_CPP11
190 #ifdef ZMQ_CPP11_PARTIAL
191 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
192 #else
193 #include <type_traits>
194 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
195 #endif
196 #endif
197 
198 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
199 #define ZMQ_NEW_MONITOR_EVENT_LAYOUT
200 #endif
201 
202 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
203 #define ZMQ_HAS_PROXY_STEERABLE
204 /* Socket event data */
205 typedef struct
206 {
207  uint16_t event; // id of the event as bitfield
208  int32_t value; // value is either error code, fd or reconnect interval
209 } zmq_event_t;
210 #endif
211 
212 // Avoid using deprecated message receive function when possible
213 #if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
214 #define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
215 #endif
216 
217 
218 // In order to prevent unused variable warnings when building in non-debug
219 // mode use this macro to make assertions.
220 #ifndef NDEBUG
221 #define ZMQ_ASSERT(expression) assert(expression)
222 #else
223 #define ZMQ_ASSERT(expression) (void) (expression)
224 #endif
225 
226 namespace zmq
227 {
228 #ifdef ZMQ_CPP11
229 namespace detail
230 {
231 namespace ranges
232 {
233 using std::begin;
234 using std::end;
235 template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
236 {
237  return begin(std::forward<T>(r));
238 }
239 template<class T> auto end(T &&r) -> decltype(end(std::forward<T>(r)))
240 {
241  return end(std::forward<T>(r));
242 }
243 } // namespace ranges
244 
245 template<class T> using void_t = void;
246 
247 template<class Iter>
248 using iter_value_t = typename std::iterator_traits<Iter>::value_type;
249 
250 template<class Range>
251 using range_iter_t = decltype(
252  ranges::begin(std::declval<typename std::remove_reference<Range>::type &>()));
253 
254 template<class Range> using range_value_t = iter_value_t<range_iter_t<Range>>;
255 
256 template<class T, class = void> struct is_range : std::false_type
257 {
258 };
259 
260 template<class T>
261 struct is_range<
262  T,
263  void_t<decltype(
264  ranges::begin(std::declval<typename std::remove_reference<T>::type &>())
265  == ranges::end(std::declval<typename std::remove_reference<T>::type &>()))>>
266  : std::true_type
267 {
268 };
269 
270 } // namespace detail
271 #endif
272 
273 typedef zmq_free_fn free_fn;
274 typedef zmq_pollitem_t pollitem_t;
275 
276 // duplicate definition from libzmq 4.3.3
277 #if defined _WIN32
278 #if defined _WIN64
279 typedef unsigned __int64 fd_t;
280 #else
281 typedef unsigned int fd_t;
282 #endif
283 #else
284 typedef int fd_t;
285 #endif
286 
287 class error_t : public std::exception
288 {
289  public:
290  error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
291  explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
292  virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
293  {
294  return zmq_strerror(errnum);
295  }
296  int num() const ZMQ_NOTHROW { return errnum; }
297 
298  private:
299  int errnum;
300 };
301 
302 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1)
303 {
304  int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
305  if (rc < 0)
306  throw error_t();
307  return rc;
308 }
309 
310 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
311 inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1)
312 {
313  return poll(const_cast<zmq_pollitem_t *>(items_), nitems_, timeout_);
314 }
315 
316 #ifdef ZMQ_CPP11
317 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
318 inline int
319 poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout)
320 {
321  return poll(const_cast<zmq_pollitem_t *>(items), nitems,
322  static_cast<long>(timeout.count()));
323 }
324 
325 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
326 inline int poll(std::vector<zmq_pollitem_t> const &items,
327  std::chrono::milliseconds timeout)
328 {
329  return poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(),
330  static_cast<long>(timeout.count()));
331 }
332 
333 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
334 inline int poll(std::vector<zmq_pollitem_t> const &items, long timeout_ = -1)
335 {
336  return poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(), timeout_);
337 }
338 
339 inline int
340 poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout)
341 {
342  return poll(items, nitems, static_cast<long>(timeout.count()));
343 }
344 
345 inline int poll(std::vector<zmq_pollitem_t> &items,
346  std::chrono::milliseconds timeout)
347 {
348  return poll(items.data(), items.size(), static_cast<long>(timeout.count()));
349 }
350 
351 ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono instead of long")
352 inline int poll(std::vector<zmq_pollitem_t> &items, long timeout_ = -1)
353 {
354  return poll(items.data(), items.size(), timeout_);
355 }
356 
357 template<std::size_t SIZE>
358 inline int poll(std::array<zmq_pollitem_t, SIZE> &items,
359  std::chrono::milliseconds timeout)
360 {
361  return poll(items.data(), items.size(), static_cast<long>(timeout.count()));
362 }
363 #endif
364 
365 
366 inline void version(int *major_, int *minor_, int *patch_)
367 {
368  zmq_version(major_, minor_, patch_);
369 }
370 
371 #ifdef ZMQ_CPP11
372 inline std::tuple<int, int, int> version()
373 {
374  std::tuple<int, int, int> v;
375  zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
376  return v;
377 }
378 
379 #if !defined(ZMQ_CPP11_PARTIAL)
380 namespace detail
381 {
382 template<class T> struct is_char_type
383 {
384  // true if character type for string literals in C++11
385  static constexpr bool value =
386  std::is_same<T, char>::value || std::is_same<T, wchar_t>::value
387  || std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value;
388 };
389 }
390 #endif
391 
392 #endif
393 
395 {
396  public:
398  {
399  int rc = zmq_msg_init(&msg);
400  ZMQ_ASSERT(rc == 0);
401  }
402 
403  explicit message_t(size_t size_)
404  {
405  int rc = zmq_msg_init_size(&msg, size_);
406  if (rc != 0)
407  throw error_t();
408  }
409 
410  template<class ForwardIter> message_t(ForwardIter first, ForwardIter last)
411  {
412  typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
413 
414  assert(std::distance(first, last) >= 0);
415  size_t const size_ =
416  static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
417  int const rc = zmq_msg_init_size(&msg, size_);
418  if (rc != 0)
419  throw error_t();
420  std::copy(first, last, data<value_t>());
421  }
422 
423  message_t(const void *data_, size_t size_)
424  {
425  int rc = zmq_msg_init_size(&msg, size_);
426  if (rc != 0)
427  throw error_t();
428  if (size_) {
429  // this constructor allows (nullptr, 0),
430  // memcpy with a null pointer is UB
431  memcpy(data(), data_, size_);
432  }
433  }
434 
435  message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
436  {
437  int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
438  if (rc != 0)
439  throw error_t();
440  }
441 
442  // overload set of string-like types and generic containers
443 #if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
444  // NOTE this constructor will include the null terminator
445  // when called with a string literal.
446  // An overload taking const char* can not be added because
447  // it would be preferred over this function and break compatiblity.
448  template<
449  class Char,
450  size_t N,
451  typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
452  ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
453  "or strings instead")
454  explicit message_t(const Char (&data)[N]) :
455  message_t(detail::ranges::begin(data), detail::ranges::end(data))
456  {
457  }
458 
459  template<class Range,
460  typename = typename std::enable_if<
461  detail::is_range<Range>::value
462  && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>)
463  && !detail::is_char_type<detail::range_value_t<Range>>::value
464  && !std::is_same<Range, message_t>::value>::type>
465  explicit message_t(const Range &rng) :
466  message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
467  {
468  }
469 
470  explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
471 
472 #if CPPZMQ_HAS_STRING_VIEW
473  explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {}
474 #endif
475 
476 #endif
477 
478 #ifdef ZMQ_HAS_RVALUE_REFS
479  message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg)
480  {
481  int rc = zmq_msg_init(&rhs.msg);
482  ZMQ_ASSERT(rc == 0);
483  }
484 
485  message_t &operator=(message_t &&rhs) ZMQ_NOTHROW
486  {
487  std::swap(msg, rhs.msg);
488  return *this;
489  }
490 #endif
491 
493  {
494  int rc = zmq_msg_close(&msg);
495  ZMQ_ASSERT(rc == 0);
496  }
497 
498  void rebuild()
499  {
500  int rc = zmq_msg_close(&msg);
501  if (rc != 0)
502  throw error_t();
503  rc = zmq_msg_init(&msg);
504  ZMQ_ASSERT(rc == 0);
505  }
506 
507  void rebuild(size_t size_)
508  {
509  int rc = zmq_msg_close(&msg);
510  if (rc != 0)
511  throw error_t();
512  rc = zmq_msg_init_size(&msg, size_);
513  if (rc != 0)
514  throw error_t();
515  }
516 
517  void rebuild(const void *data_, size_t size_)
518  {
519  int rc = zmq_msg_close(&msg);
520  if (rc != 0)
521  throw error_t();
522  rc = zmq_msg_init_size(&msg, size_);
523  if (rc != 0)
524  throw error_t();
525  memcpy(data(), data_, size_);
526  }
527 
528  void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
529  {
530  int rc = zmq_msg_close(&msg);
531  if (rc != 0)
532  throw error_t();
533  rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
534  if (rc != 0)
535  throw error_t();
536  }
537 
538  ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
539  void move(message_t const *msg_)
540  {
541  int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
542  if (rc != 0)
543  throw error_t();
544  }
545 
546  void move(message_t &msg_)
547  {
548  int rc = zmq_msg_move(&msg, msg_.handle());
549  if (rc != 0)
550  throw error_t();
551  }
552 
553  ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
554  void copy(message_t const *msg_)
555  {
556  int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
557  if (rc != 0)
558  throw error_t();
559  }
560 
561  void copy(message_t &msg_)
562  {
563  int rc = zmq_msg_copy(&msg, msg_.handle());
564  if (rc != 0)
565  throw error_t();
566  }
567 
568  bool more() const ZMQ_NOTHROW
569  {
570  int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
571  return rc != 0;
572  }
573 
574  void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
575 
576  const void *data() const ZMQ_NOTHROW
577  {
578  return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
579  }
580 
581  size_t size() const ZMQ_NOTHROW
582  {
583  return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
584  }
585 
586  ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
587 
588  template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
589 
590  template<typename T> T const *data() const ZMQ_NOTHROW
591  {
592  return static_cast<T const *>(data());
593  }
594 
595  ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
596  bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
597 
598  bool operator==(const message_t &other) const ZMQ_NOTHROW
599  {
600  const size_t my_size = size();
601  return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
602  }
603 
604  bool operator!=(const message_t &other) const ZMQ_NOTHROW
605  {
606  return !(*this == other);
607  }
608 
609 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
610  int get(int property_)
611  {
612  int value = zmq_msg_get(&msg, property_);
613  if (value == -1)
614  throw error_t();
615  return value;
616  }
617 #endif
618 
619 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
620  const char *gets(const char *property_)
621  {
622  const char *value = zmq_msg_gets(&msg, property_);
623  if (value == ZMQ_NULLPTR)
624  throw error_t();
625  return value;
626  }
627 #endif
628 
629 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
630  uint32_t routing_id() const
631  {
632  return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
633  }
634 
635  void set_routing_id(uint32_t routing_id)
636  {
637  int rc = zmq_msg_set_routing_id(&msg, routing_id);
638  if (rc != 0)
639  throw error_t();
640  }
641 
642  const char *group() const
643  {
644  return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
645  }
646 
647  void set_group(const char *group)
648  {
649  int rc = zmq_msg_set_group(&msg, group);
650  if (rc != 0)
651  throw error_t();
652  }
653 #endif
654 
655  // interpret message content as a string
656  std::string to_string() const
657  {
658  return std::string(static_cast<const char *>(data()), size());
659  }
660 #if CPPZMQ_HAS_STRING_VIEW
661  // interpret message content as a string
662  std::string_view to_string_view() const noexcept
663  {
664  return std::string_view(static_cast<const char *>(data()), size());
665  }
666 #endif
667 
674  std::string str() const
675  {
676  // Partly mutuated from the same method in zmq::multipart_t
677  std::stringstream os;
678 
679  const unsigned char *msg_data = this->data<unsigned char>();
680  unsigned char byte;
681  size_t size = this->size();
682  int is_ascii[2] = {0, 0};
683 
684  os << "zmq::message_t [size " << std::dec << std::setw(3)
685  << std::setfill('0') << size << "] (";
686  // Totally arbitrary
687  if (size >= 1000) {
688  os << "... too big to print)";
689  } else {
690  while (size--) {
691  byte = *msg_data++;
692 
693  is_ascii[1] = (byte >= 32 && byte < 127);
694  if (is_ascii[1] != is_ascii[0])
695  os << " "; // Separate text/non text
696 
697  if (is_ascii[1]) {
698  os << byte;
699  } else {
700  os << std::hex << std::uppercase << std::setw(2)
701  << std::setfill('0') << static_cast<short>(byte);
702  }
703  is_ascii[0] = is_ascii[1];
704  }
705  os << ")";
706  }
707  return os.str();
708  }
709 
711  {
712  // this assumes zmq::msg_t from libzmq is trivially relocatable
713  std::swap(msg, other.msg);
714  }
715 
716  ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
717  ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; }
718 
719  private:
720  // The underlying message
721  zmq_msg_t msg;
722 
723  // Disable implicit message copying, so that users won't use shared
724  // messages (less efficient) without being aware of the fact.
726  void operator=(const message_t &) ZMQ_DELETED_FUNCTION;
727 };
728 
729 inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
730 {
731  a.swap(b);
732 }
733 
734 #ifdef ZMQ_CPP11
735 enum class ctxopt
736 {
737 #ifdef ZMQ_BLOCKY
738  blocky = ZMQ_BLOCKY,
739 #endif
740 #ifdef ZMQ_IO_THREADS
741  io_threads = ZMQ_IO_THREADS,
742 #endif
743 #ifdef ZMQ_THREAD_SCHED_POLICY
744  thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
745 #endif
746 #ifdef ZMQ_THREAD_PRIORITY
747  thread_priority = ZMQ_THREAD_PRIORITY,
748 #endif
749 #ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
750  thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
751 #endif
752 #ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
753  thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
754 #endif
755 #ifdef ZMQ_THREAD_NAME_PREFIX
756  thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
757 #endif
758 #ifdef ZMQ_MAX_MSGSZ
759  max_msgsz = ZMQ_MAX_MSGSZ,
760 #endif
761 #ifdef ZMQ_ZERO_COPY_RECV
762  zero_copy_recv = ZMQ_ZERO_COPY_RECV,
763 #endif
764 #ifdef ZMQ_MAX_SOCKETS
765  max_sockets = ZMQ_MAX_SOCKETS,
766 #endif
767 #ifdef ZMQ_SOCKET_LIMIT
768  socket_limit = ZMQ_SOCKET_LIMIT,
769 #endif
770 #ifdef ZMQ_IPV6
771  ipv6 = ZMQ_IPV6,
772 #endif
773 #ifdef ZMQ_MSG_T_SIZE
774  msg_t_size = ZMQ_MSG_T_SIZE
775 #endif
776 };
777 #endif
778 
780 {
781  public:
783  {
784  ptr = zmq_ctx_new();
785  if (ptr == ZMQ_NULLPTR)
786  throw error_t();
787  }
788 
789 
790  explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
791  {
792  ptr = zmq_ctx_new();
793  if (ptr == ZMQ_NULLPTR)
794  throw error_t();
795 
796  int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
797  ZMQ_ASSERT(rc == 0);
798 
799  rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
800  ZMQ_ASSERT(rc == 0);
801  }
802 
803 #ifdef ZMQ_HAS_RVALUE_REFS
804  context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
805  context_t &operator=(context_t &&rhs) ZMQ_NOTHROW
806  {
807  close();
808  std::swap(ptr, rhs.ptr);
809  return *this;
810  }
811 #endif
812 
813  ~context_t() ZMQ_NOTHROW { close(); }
814 
815  ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
816  int setctxopt(int option_, int optval_)
817  {
818  int rc = zmq_ctx_set(ptr, option_, optval_);
819  ZMQ_ASSERT(rc == 0);
820  return rc;
821  }
822 
823  ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
824  int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
825 
826 #ifdef ZMQ_CPP11
827  void set(ctxopt option, int optval)
828  {
829  int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
830  if (rc == -1)
831  throw error_t();
832  }
833 
834  ZMQ_NODISCARD int get(ctxopt option)
835  {
836  int rc = zmq_ctx_get(ptr, static_cast<int>(option));
837  // some options have a default value of -1
838  // which is unfortunate, and may result in errors
839  // that don't make sense
840  if (rc == -1)
841  throw error_t();
842  return rc;
843  }
844 #endif
845 
846  // Terminates context (see also shutdown()).
848  {
849  if (ptr == ZMQ_NULLPTR)
850  return;
851 
852  int rc;
853  do {
854  rc = zmq_ctx_destroy(ptr);
855  } while (rc == -1 && errno == EINTR);
856 
857  ZMQ_ASSERT(rc == 0);
858  ptr = ZMQ_NULLPTR;
859  }
860 
861  // Shutdown context in preparation for termination (close()).
862  // Causes all blocking socket operations and any further
863  // socket operations to return with ETERM.
865  {
866  if (ptr == ZMQ_NULLPTR)
867  return;
868  int rc = zmq_ctx_shutdown(ptr);
869  ZMQ_ASSERT(rc == 0);
870  }
871 
872  // Be careful with this, it's probably only useful for
873  // using the C api together with an existing C++ api.
874  // Normally you should never need to use this.
875  ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
876 
877  ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
878 
879  ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
880 
881  ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
882  operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
883 
884  void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); }
885 
886  private:
887  void *ptr;
888 
890  void operator=(const context_t &) ZMQ_DELETED_FUNCTION;
891 };
892 
893 inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW
894 {
895  a.swap(b);
896 }
897 
898 #ifdef ZMQ_CPP11
899 
900 struct recv_buffer_size
901 {
902  size_t size; // number of bytes written to buffer
903  size_t untruncated_size; // untruncated message size in bytes
904 
905  ZMQ_NODISCARD bool truncated() const noexcept
906  {
907  return size != untruncated_size;
908  }
909 };
910 
911 #if CPPZMQ_HAS_OPTIONAL
912 
913 using send_result_t = std::optional<size_t>;
914 using recv_result_t = std::optional<size_t>;
915 using recv_buffer_result_t = std::optional<recv_buffer_size>;
916 
917 #else
918 
919 namespace detail
920 {
921 // A C++11 type emulating the most basic
922 // operations of std::optional for trivial types
923 template<class T> class trivial_optional
924 {
925  public:
926  static_assert(std::is_trivial<T>::value, "T must be trivial");
927  using value_type = T;
928 
929  trivial_optional() = default;
930  trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
931 
932  const T *operator->() const noexcept
933  {
934  assert(_has_value);
935  return &_value;
936  }
937  T *operator->() noexcept
938  {
939  assert(_has_value);
940  return &_value;
941  }
942 
943  const T &operator*() const noexcept
944  {
945  assert(_has_value);
946  return _value;
947  }
948  T &operator*() noexcept
949  {
950  assert(_has_value);
951  return _value;
952  }
953 
954  T &value()
955  {
956  if (!_has_value)
957  throw std::exception();
958  return _value;
959  }
960  const T &value() const
961  {
962  if (!_has_value)
963  throw std::exception();
964  return _value;
965  }
966 
967  explicit operator bool() const noexcept { return _has_value; }
968  bool has_value() const noexcept { return _has_value; }
969 
970  private:
971  T _value{};
972  bool _has_value{false};
973 };
974 } // namespace detail
975 
976 using send_result_t = detail::trivial_optional<size_t>;
977 using recv_result_t = detail::trivial_optional<size_t>;
978 using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
979 
980 #endif
981 
982 namespace detail
983 {
984 template<class T> constexpr T enum_bit_or(T a, T b) noexcept
985 {
986  static_assert(std::is_enum<T>::value, "must be enum");
987  using U = typename std::underlying_type<T>::type;
988  return static_cast<T>(static_cast<U>(a) | static_cast<U>(b));
989 }
990 template<class T> constexpr T enum_bit_and(T a, T b) noexcept
991 {
992  static_assert(std::is_enum<T>::value, "must be enum");
993  using U = typename std::underlying_type<T>::type;
994  return static_cast<T>(static_cast<U>(a) & static_cast<U>(b));
995 }
996 template<class T> constexpr T enum_bit_xor(T a, T b) noexcept
997 {
998  static_assert(std::is_enum<T>::value, "must be enum");
999  using U = typename std::underlying_type<T>::type;
1000  return static_cast<T>(static_cast<U>(a) ^ static_cast<U>(b));
1001 }
1002 template<class T> constexpr T enum_bit_not(T a) noexcept
1003 {
1004  static_assert(std::is_enum<T>::value, "must be enum");
1005  using U = typename std::underlying_type<T>::type;
1006  return static_cast<T>(~static_cast<U>(a));
1007 }
1008 } // namespace detail
1009 
1010 // partially satisfies named requirement BitmaskType
1011 enum class send_flags : int
1012 {
1013  none = 0,
1014  dontwait = ZMQ_DONTWAIT,
1015  sndmore = ZMQ_SNDMORE
1016 };
1017 
1018 constexpr send_flags operator|(send_flags a, send_flags b) noexcept
1019 {
1020  return detail::enum_bit_or(a, b);
1021 }
1022 constexpr send_flags operator&(send_flags a, send_flags b) noexcept
1023 {
1024  return detail::enum_bit_and(a, b);
1025 }
1026 constexpr send_flags operator^(send_flags a, send_flags b) noexcept
1027 {
1028  return detail::enum_bit_xor(a, b);
1029 }
1030 constexpr send_flags operator~(send_flags a) noexcept
1031 {
1032  return detail::enum_bit_not(a);
1033 }
1034 
1035 // partially satisfies named requirement BitmaskType
1036 enum class recv_flags : int
1037 {
1038  none = 0,
1039  dontwait = ZMQ_DONTWAIT
1040 };
1041 
1042 constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept
1043 {
1044  return detail::enum_bit_or(a, b);
1045 }
1046 constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept
1047 {
1048  return detail::enum_bit_and(a, b);
1049 }
1050 constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept
1051 {
1052  return detail::enum_bit_xor(a, b);
1053 }
1054 constexpr recv_flags operator~(recv_flags a) noexcept
1055 {
1056  return detail::enum_bit_not(a);
1057 }
1058 
1059 
1060 // mutable_buffer, const_buffer and buffer are based on
1061 // the Networking TS specification, draft:
1062 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
1063 
1064 class mutable_buffer
1065 {
1066  public:
1067  constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
1068  constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
1069  {
1070 #ifdef ZMQ_EXTENDED_CONSTEXPR
1071  assert(p != nullptr || n == 0);
1072 #endif
1073  }
1074 
1075  constexpr void *data() const noexcept { return _data; }
1076  constexpr size_t size() const noexcept { return _size; }
1077  mutable_buffer &operator+=(size_t n) noexcept
1078  {
1079  // (std::min) is a workaround for when a min macro is defined
1080  const auto shift = (std::min)(n, _size);
1081  _data = static_cast<char *>(_data) + shift;
1082  _size -= shift;
1083  return *this;
1084  }
1085 
1086  private:
1087  void *_data;
1088  size_t _size;
1089 };
1090 
1091 inline mutable_buffer operator+(const mutable_buffer &mb, size_t n) noexcept
1092 {
1093  return mutable_buffer(static_cast<char *>(mb.data()) + (std::min)(n, mb.size()),
1094  mb.size() - (std::min)(n, mb.size()));
1095 }
1096 inline mutable_buffer operator+(size_t n, const mutable_buffer &mb) noexcept
1097 {
1098  return mb + n;
1099 }
1100 
1101 class const_buffer
1102 {
1103  public:
1104  constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
1105  constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
1106  {
1107 #ifdef ZMQ_EXTENDED_CONSTEXPR
1108  assert(p != nullptr || n == 0);
1109 #endif
1110  }
1111  constexpr const_buffer(const mutable_buffer &mb) noexcept :
1112  _data(mb.data()), _size(mb.size())
1113  {
1114  }
1115 
1116  constexpr const void *data() const noexcept { return _data; }
1117  constexpr size_t size() const noexcept { return _size; }
1118  const_buffer &operator+=(size_t n) noexcept
1119  {
1120  const auto shift = (std::min)(n, _size);
1121  _data = static_cast<const char *>(_data) + shift;
1122  _size -= shift;
1123  return *this;
1124  }
1125 
1126  private:
1127  const void *_data;
1128  size_t _size;
1129 };
1130 
1131 inline const_buffer operator+(const const_buffer &cb, size_t n) noexcept
1132 {
1133  return const_buffer(static_cast<const char *>(cb.data())
1134  + (std::min)(n, cb.size()),
1135  cb.size() - (std::min)(n, cb.size()));
1136 }
1137 inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept
1138 {
1139  return cb + n;
1140 }
1141 
1142 // buffer creation
1143 
1144 constexpr mutable_buffer buffer(void *p, size_t n) noexcept
1145 {
1146  return mutable_buffer(p, n);
1147 }
1148 constexpr const_buffer buffer(const void *p, size_t n) noexcept
1149 {
1150  return const_buffer(p, n);
1151 }
1152 constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept
1153 {
1154  return mb;
1155 }
1156 inline mutable_buffer buffer(const mutable_buffer &mb, size_t n) noexcept
1157 {
1158  return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
1159 }
1160 constexpr const_buffer buffer(const const_buffer &cb) noexcept
1161 {
1162  return cb;
1163 }
1164 inline const_buffer buffer(const const_buffer &cb, size_t n) noexcept
1165 {
1166  return const_buffer(cb.data(), (std::min)(cb.size(), n));
1167 }
1168 
1169 namespace detail
1170 {
1171 template<class T> struct is_buffer
1172 {
1173  static constexpr bool value =
1174  std::is_same<T, const_buffer>::value || std::is_same<T, mutable_buffer>::value;
1175 };
1176 
1177 template<class T> struct is_pod_like
1178 {
1179  // NOTE: The networking draft N4771 section 16.11 requires
1180  // T in the buffer functions below to be
1181  // trivially copyable OR standard layout.
1182  // Here we decide to be conservative and require both.
1183  static constexpr bool value =
1184  ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout<T>::value;
1185 };
1186 
1187 template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
1188 {
1189  return c.size();
1190 }
1191 template<class T, size_t N>
1192 constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
1193 {
1194  return N;
1195 }
1196 
1197 template<class Seq>
1198 auto buffer_contiguous_sequence(Seq &&seq) noexcept
1199  -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
1200 {
1201  using T = typename std::remove_cv<
1202  typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1203  static_assert(detail::is_pod_like<T>::value, "T must be POD");
1204 
1205  const auto size = seq_size(seq);
1206  return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1207  size * sizeof(T));
1208 }
1209 template<class Seq>
1210 auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
1211  -> decltype(buffer_contiguous_sequence(seq))
1212 {
1213  using T = typename std::remove_cv<
1214  typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
1215  static_assert(detail::is_pod_like<T>::value, "T must be POD");
1216 
1217  const auto size = seq_size(seq);
1218  return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
1219  (std::min)(size * sizeof(T), n_bytes));
1220 }
1221 
1222 } // namespace detail
1223 
1224 // C array
1225 template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
1226 {
1227  return detail::buffer_contiguous_sequence(data);
1228 }
1229 template<class T, size_t N>
1230 mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
1231 {
1232  return detail::buffer_contiguous_sequence(data, n_bytes);
1233 }
1234 template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
1235 {
1236  return detail::buffer_contiguous_sequence(data);
1237 }
1238 template<class T, size_t N>
1239 const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
1240 {
1241  return detail::buffer_contiguous_sequence(data, n_bytes);
1242 }
1243 // std::array
1244 template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
1245 {
1246  return detail::buffer_contiguous_sequence(data);
1247 }
1248 template<class T, size_t N>
1249 mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
1250 {
1251  return detail::buffer_contiguous_sequence(data, n_bytes);
1252 }
1253 template<class T, size_t N>
1254 const_buffer buffer(std::array<const T, N> &data) noexcept
1255 {
1256  return detail::buffer_contiguous_sequence(data);
1257 }
1258 template<class T, size_t N>
1259 const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
1260 {
1261  return detail::buffer_contiguous_sequence(data, n_bytes);
1262 }
1263 template<class T, size_t N>
1264 const_buffer buffer(const std::array<T, N> &data) noexcept
1265 {
1266  return detail::buffer_contiguous_sequence(data);
1267 }
1268 template<class T, size_t N>
1269 const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
1270 {
1271  return detail::buffer_contiguous_sequence(data, n_bytes);
1272 }
1273 // std::vector
1274 template<class T, class Allocator>
1275 mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
1276 {
1277  return detail::buffer_contiguous_sequence(data);
1278 }
1279 template<class T, class Allocator>
1280 mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1281 {
1282  return detail::buffer_contiguous_sequence(data, n_bytes);
1283 }
1284 template<class T, class Allocator>
1285 const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
1286 {
1287  return detail::buffer_contiguous_sequence(data);
1288 }
1289 template<class T, class Allocator>
1290 const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
1291 {
1292  return detail::buffer_contiguous_sequence(data, n_bytes);
1293 }
1294 // std::basic_string
1295 template<class T, class Traits, class Allocator>
1296 mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
1297 {
1298  return detail::buffer_contiguous_sequence(data);
1299 }
1300 template<class T, class Traits, class Allocator>
1301 mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
1302  size_t n_bytes) noexcept
1303 {
1304  return detail::buffer_contiguous_sequence(data, n_bytes);
1305 }
1306 template<class T, class Traits, class Allocator>
1307 const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
1308 {
1309  return detail::buffer_contiguous_sequence(data);
1310 }
1311 template<class T, class Traits, class Allocator>
1312 const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
1313  size_t n_bytes) noexcept
1314 {
1315  return detail::buffer_contiguous_sequence(data, n_bytes);
1316 }
1317 
1318 #if CPPZMQ_HAS_STRING_VIEW
1319 // std::basic_string_view
1320 template<class T, class Traits>
1321 const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
1322 {
1323  return detail::buffer_contiguous_sequence(data);
1324 }
1325 template<class T, class Traits>
1326 const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1327 {
1328  return detail::buffer_contiguous_sequence(data, n_bytes);
1329 }
1330 #endif
1331 
1332 // Buffer for a string literal (null terminated)
1333 // where the buffer size excludes the terminating character.
1334 // Equivalent to zmq::buffer(std::string_view("...")).
1335 template<class Char, size_t N>
1336 constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept
1337 {
1338  static_assert(detail::is_pod_like<Char>::value, "Char must be POD");
1339 #ifdef ZMQ_EXTENDED_CONSTEXPR
1340  assert(data[N - 1] == Char{0});
1341 #endif
1342  return const_buffer(static_cast<const Char *>(data), (N - 1) * sizeof(Char));
1343 }
1344 
1345 namespace literals
1346 {
1347 constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept
1348 {
1349  return const_buffer(str, len * sizeof(char));
1350 }
1351 constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept
1352 {
1353  return const_buffer(str, len * sizeof(wchar_t));
1354 }
1355 constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept
1356 {
1357  return const_buffer(str, len * sizeof(char16_t));
1358 }
1359 constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept
1360 {
1361  return const_buffer(str, len * sizeof(char32_t));
1362 }
1363 }
1364 
1365 namespace sockopt
1366 {
1367 // There are two types of options,
1368 // integral type with known compiler time size (int, bool, int64_t, uint64_t)
1369 // and arrays with dynamic size (strings, binary data).
1370 
1371 // BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1372 template<int Opt, class T, bool BoolUnit = false> struct integral_option
1373 {
1374 };
1375 
1376 // NullTerm:
1377 // 0: binary data
1378 // 1: null-terminated string (`getsockopt` size includes null)
1379 // 2: binary (size 32) or Z85 encoder string of size 41 (null included)
1380 template<int Opt, int NullTerm = 1> struct array_option
1381 {
1382 };
1383 
1384 #define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \
1385  using NAME##_t = integral_option<OPT, TYPE, false>; \
1386  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1387 #define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \
1388  using NAME##_t = integral_option<OPT, TYPE, true>; \
1389  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1390 #define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \
1391  using NAME##_t = array_option<OPT>; \
1392  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1393 #define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \
1394  using NAME##_t = array_option<OPT, 0>; \
1395  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1396 #define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \
1397  using NAME##_t = array_option<OPT, 2>; \
1398  ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {}
1399 
1400 // deprecated, use zmq::fd_t
1401 using cppzmq_fd_t = ::zmq::fd_t;
1402 
1403 #ifdef ZMQ_AFFINITY
1404 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t);
1405 #endif
1406 #ifdef ZMQ_BACKLOG
1407 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int);
1408 #endif
1409 #ifdef ZMQ_BINDTODEVICE
1410 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice);
1411 #endif
1412 #ifdef ZMQ_CONFLATE
1413 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int);
1414 #endif
1415 #ifdef ZMQ_CONNECT_ROUTING_ID
1416 ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id);
1417 #endif
1418 #ifdef ZMQ_CONNECT_TIMEOUT
1419 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int);
1420 #endif
1421 #ifdef ZMQ_CURVE_PUBLICKEY
1422 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey);
1423 #endif
1424 #ifdef ZMQ_CURVE_SECRETKEY
1425 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey);
1426 #endif
1427 #ifdef ZMQ_CURVE_SERVER
1428 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int);
1429 #endif
1430 #ifdef ZMQ_CURVE_SERVERKEY
1431 ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey);
1432 #endif
1433 #ifdef ZMQ_EVENTS
1434 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int);
1435 #endif
1436 #ifdef ZMQ_FD
1437 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, ::zmq::fd_t);
1438 #endif
1439 #ifdef ZMQ_GSSAPI_PLAINTEXT
1440 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int);
1441 #endif
1442 #ifdef ZMQ_GSSAPI_SERVER
1443 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int);
1444 #endif
1445 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL
1446 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal);
1447 #endif
1448 #ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE
1449 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE,
1450  gssapi_service_principal_nametype,
1451  int);
1452 #endif
1453 #ifdef ZMQ_GSSAPI_PRINCIPAL
1454 ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal);
1455 #endif
1456 #ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE
1457 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE,
1458  gssapi_principal_nametype,
1459  int);
1460 #endif
1461 #ifdef ZMQ_HANDSHAKE_IVL
1462 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int);
1463 #endif
1464 #ifdef ZMQ_HEARTBEAT_IVL
1465 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int);
1466 #endif
1467 #ifdef ZMQ_HEARTBEAT_TIMEOUT
1468 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int);
1469 #endif
1470 #ifdef ZMQ_HEARTBEAT_TTL
1471 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int);
1472 #endif
1473 #ifdef ZMQ_IMMEDIATE
1474 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int);
1475 #endif
1476 #ifdef ZMQ_INVERT_MATCHING
1477 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int);
1478 #endif
1479 #ifdef ZMQ_IPV6
1480 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int);
1481 #endif
1482 #ifdef ZMQ_LAST_ENDPOINT
1483 ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint);
1484 #endif
1485 #ifdef ZMQ_LINGER
1486 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int);
1487 #endif
1488 #ifdef ZMQ_MAXMSGSIZE
1489 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t);
1490 #endif
1491 #ifdef ZMQ_MECHANISM
1492 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int);
1493 #endif
1494 #ifdef ZMQ_METADATA
1495 ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata);
1496 #endif
1497 #ifdef ZMQ_MULTICAST_HOPS
1498 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int);
1499 #endif
1500 #ifdef ZMQ_MULTICAST_LOOP
1501 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int);
1502 #endif
1503 #ifdef ZMQ_MULTICAST_MAXTPDU
1504 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int);
1505 #endif
1506 #ifdef ZMQ_PLAIN_SERVER
1507 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int);
1508 #endif
1509 #ifdef ZMQ_PLAIN_PASSWORD
1510 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password);
1511 #endif
1512 #ifdef ZMQ_PLAIN_USERNAME
1513 ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username);
1514 #endif
1515 #ifdef ZMQ_USE_FD
1516 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int);
1517 #endif
1518 #ifdef ZMQ_PROBE_ROUTER
1519 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int);
1520 #endif
1521 #ifdef ZMQ_RATE
1522 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int);
1523 #endif
1524 #ifdef ZMQ_RCVBUF
1525 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int);
1526 #endif
1527 #ifdef ZMQ_RCVHWM
1528 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int);
1529 #endif
1530 #ifdef ZMQ_RCVMORE
1531 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int);
1532 #endif
1533 #ifdef ZMQ_RCVTIMEO
1534 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int);
1535 #endif
1536 #ifdef ZMQ_RECONNECT_IVL
1537 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int);
1538 #endif
1539 #ifdef ZMQ_RECONNECT_IVL_MAX
1540 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int);
1541 #endif
1542 #ifdef ZMQ_RECOVERY_IVL
1543 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int);
1544 #endif
1545 #ifdef ZMQ_REQ_CORRELATE
1546 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int);
1547 #endif
1548 #ifdef ZMQ_REQ_RELAXED
1549 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int);
1550 #endif
1551 #ifdef ZMQ_ROUTER_HANDOVER
1552 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int);
1553 #endif
1554 #ifdef ZMQ_ROUTER_MANDATORY
1555 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int);
1556 #endif
1557 #ifdef ZMQ_ROUTER_NOTIFY
1558 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int);
1559 #endif
1560 #ifdef ZMQ_ROUTING_ID
1561 ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id);
1562 #endif
1563 #ifdef ZMQ_SNDBUF
1564 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int);
1565 #endif
1566 #ifdef ZMQ_SNDHWM
1567 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int);
1568 #endif
1569 #ifdef ZMQ_SNDTIMEO
1570 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int);
1571 #endif
1572 #ifdef ZMQ_SOCKS_PROXY
1573 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy);
1574 #endif
1575 #ifdef ZMQ_STREAM_NOTIFY
1576 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int);
1577 #endif
1578 #ifdef ZMQ_SUBSCRIBE
1579 ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe);
1580 #endif
1581 #ifdef ZMQ_TCP_KEEPALIVE
1582 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int);
1583 #endif
1584 #ifdef ZMQ_TCP_KEEPALIVE_CNT
1585 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int);
1586 #endif
1587 #ifdef ZMQ_TCP_KEEPALIVE_IDLE
1588 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int);
1589 #endif
1590 #ifdef ZMQ_TCP_KEEPALIVE_INTVL
1591 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int);
1592 #endif
1593 #ifdef ZMQ_TCP_MAXRT
1594 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int);
1595 #endif
1596 #ifdef ZMQ_THREAD_SAFE
1597 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int);
1598 #endif
1599 #ifdef ZMQ_TOS
1600 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int);
1601 #endif
1602 #ifdef ZMQ_TYPE
1603 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int);
1604 #endif
1605 #ifdef ZMQ_UNSUBSCRIBE
1606 ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe);
1607 #endif
1608 #ifdef ZMQ_VMCI_BUFFER_SIZE
1609 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t);
1610 #endif
1611 #ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
1612 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t);
1613 #endif
1614 #ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
1615 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t);
1616 #endif
1617 #ifdef ZMQ_VMCI_CONNECT_TIMEOUT
1618 ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int);
1619 #endif
1620 #ifdef ZMQ_XPUB_VERBOSE
1621 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int);
1622 #endif
1623 #ifdef ZMQ_XPUB_VERBOSER
1624 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int);
1625 #endif
1626 #ifdef ZMQ_XPUB_MANUAL
1627 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int);
1628 #endif
1629 #ifdef ZMQ_XPUB_NODROP
1630 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int);
1631 #endif
1632 #ifdef ZMQ_XPUB_WELCOME_MSG
1633 ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg);
1634 #endif
1635 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
1636 ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int);
1637 #endif
1638 #ifdef ZMQ_ZAP_DOMAIN
1639 ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain);
1640 #endif
1641 
1642 } // namespace sockopt
1643 #endif // ZMQ_CPP11
1644 
1645 
1646 namespace detail
1647 {
1649 {
1650  public:
1652  ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {}
1653 
1654  template<typename T>
1655  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1656  void setsockopt(int option_, T const &optval)
1657  {
1658  setsockopt(option_, &optval, sizeof(T));
1659  }
1660 
1661  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt")
1662  void setsockopt(int option_, const void *optval_, size_t optvallen_)
1663  {
1664  int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
1665  if (rc != 0)
1666  throw error_t();
1667  }
1668 
1669  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1670  void getsockopt(int option_, void *optval_, size_t *optvallen_) const
1671  {
1672  int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
1673  if (rc != 0)
1674  throw error_t();
1675  }
1676 
1677  template<typename T>
1678  ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt")
1679  T getsockopt(int option_) const
1680  {
1681  T optval;
1682  size_t optlen = sizeof(T);
1683  getsockopt(option_, &optval, &optlen);
1684  return optval;
1685  }
1686 
1687 #ifdef ZMQ_CPP11
1688  // Set integral socket option, e.g.
1689  // `socket.set(zmq::sockopt::linger, 0)`
1690  template<int Opt, class T, bool BoolUnit>
1691  void set(sockopt::integral_option<Opt, T, BoolUnit>, const T &val)
1692  {
1693  static_assert(std::is_integral<T>::value, "T must be integral");
1694  set_option(Opt, &val, sizeof val);
1695  }
1696 
1697  // Set integral socket option from boolean, e.g.
1698  // `socket.set(zmq::sockopt::immediate, false)`
1699  template<int Opt, class T>
1700  void set(sockopt::integral_option<Opt, T, true>, bool val)
1701  {
1702  static_assert(std::is_integral<T>::value, "T must be integral");
1703  T rep_val = val;
1704  set_option(Opt, &rep_val, sizeof rep_val);
1705  }
1706 
1707  // Set array socket option, e.g.
1708  // `socket.set(zmq::sockopt::plain_username, "foo123")`
1709  template<int Opt, int NullTerm>
1710  void set(sockopt::array_option<Opt, NullTerm>, const char *buf)
1711  {
1712  set_option(Opt, buf, std::strlen(buf));
1713  }
1714 
1715  // Set array socket option, e.g.
1716  // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
1717  template<int Opt, int NullTerm>
1718  void set(sockopt::array_option<Opt, NullTerm>, const_buffer buf)
1719  {
1720  set_option(Opt, buf.data(), buf.size());
1721  }
1722 
1723  // Set array socket option, e.g.
1724  // `socket.set(zmq::sockopt::routing_id, id_str)`
1725  template<int Opt, int NullTerm>
1726  void set(sockopt::array_option<Opt, NullTerm>, const std::string &buf)
1727  {
1728  set_option(Opt, buf.data(), buf.size());
1729  }
1730 
1731 #if CPPZMQ_HAS_STRING_VIEW
1732  // Set array socket option, e.g.
1733  // `socket.set(zmq::sockopt::routing_id, id_str)`
1734  template<int Opt, int NullTerm>
1735  void set(sockopt::array_option<Opt, NullTerm>, std::string_view buf)
1736  {
1737  set_option(Opt, buf.data(), buf.size());
1738  }
1739 #endif
1740 
1741  // Get scalar socket option, e.g.
1742  // `auto opt = socket.get(zmq::sockopt::linger)`
1743  template<int Opt, class T, bool BoolUnit>
1744  ZMQ_NODISCARD T get(sockopt::integral_option<Opt, T, BoolUnit>) const
1745  {
1746  static_assert(std::is_integral<T>::value, "T must be integral");
1747  T val;
1748  size_t size = sizeof val;
1749  get_option(Opt, &val, &size);
1750  assert(size == sizeof val);
1751  return val;
1752  }
1753 
1754  // Get array socket option, writes to buf, returns option size in bytes, e.g.
1755  // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
1756  template<int Opt, int NullTerm>
1757  ZMQ_NODISCARD size_t get(sockopt::array_option<Opt, NullTerm>,
1758  mutable_buffer buf) const
1759  {
1760  size_t size = buf.size();
1761  get_option(Opt, buf.data(), &size);
1762  return size;
1763  }
1764 
1765  // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1766  // `auto s = socket.get(zmq::sockopt::routing_id)`
1767  // Note: removes the null character from null-terminated string options,
1768  // i.e. the string size excludes the null character.
1769  template<int Opt, int NullTerm>
1770  ZMQ_NODISCARD std::string get(sockopt::array_option<Opt, NullTerm>,
1771  size_t init_size = 1024) const
1772  {
1773  if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1774  if (init_size == 1024) {
1775  init_size = 41; // get as Z85 string
1776  }
1777  }
1778  std::string str(init_size, '\0');
1779  size_t size = get(sockopt::array_option<Opt>{}, buffer(str));
1780  if ZMQ_CONSTEXPR_IF (NullTerm == 1) {
1781  if (size > 0) {
1782  assert(str[size - 1] == '\0');
1783  --size;
1784  }
1785  } else if ZMQ_CONSTEXPR_IF (NullTerm == 2) {
1786  assert(size == 32 || size == 41);
1787  if (size == 41) {
1788  assert(str[size - 1] == '\0');
1789  --size;
1790  }
1791  }
1792  str.resize(size);
1793  return str;
1794  }
1795 #endif
1796 
1797  void bind(std::string const &addr) { bind(addr.c_str()); }
1798 
1799  void bind(const char *addr_)
1800  {
1801  int rc = zmq_bind(_handle, addr_);
1802  if (rc != 0)
1803  throw error_t();
1804  }
1805 
1806  void unbind(std::string const &addr) { unbind(addr.c_str()); }
1807 
1808  void unbind(const char *addr_)
1809  {
1810  int rc = zmq_unbind(_handle, addr_);
1811  if (rc != 0)
1812  throw error_t();
1813  }
1814 
1815  void connect(std::string const &addr) { connect(addr.c_str()); }
1816 
1817  void connect(const char *addr_)
1818  {
1819  int rc = zmq_connect(_handle, addr_);
1820  if (rc != 0)
1821  throw error_t();
1822  }
1823 
1824  void disconnect(std::string const &addr) { disconnect(addr.c_str()); }
1825 
1826  void disconnect(const char *addr_)
1827  {
1828  int rc = zmq_disconnect(_handle, addr_);
1829  if (rc != 0)
1830  throw error_t();
1831  }
1832 
1833  ZMQ_DEPRECATED("from 4.7.1, use handle() != nullptr or operator bool")
1834  bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); }
1835 
1836  ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags")
1837  size_t send(const void *buf_, size_t len_, int flags_ = 0)
1838  {
1839  int nbytes = zmq_send(_handle, buf_, len_, flags_);
1840  if (nbytes >= 0)
1841  return static_cast<size_t>(nbytes);
1842  if (zmq_errno() == EAGAIN)
1843  return 0;
1844  throw error_t();
1845  }
1846 
1847  ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1848  bool send(message_t &msg_,
1849  int flags_ = 0) // default until removed
1850  {
1851  int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_);
1852  if (nbytes >= 0)
1853  return true;
1854  if (zmq_errno() == EAGAIN)
1855  return false;
1856  throw error_t();
1857  }
1858 
1859  template<typename T>
1861  "from 4.4.1, use send taking message_t or buffer (for contiguous "
1862  "ranges), and send_flags")
1863  bool send(T first, T last, int flags_ = 0)
1864  {
1865  zmq::message_t msg(first, last);
1866  int nbytes = zmq_msg_send(msg.handle(), _handle, flags_);
1867  if (nbytes >= 0)
1868  return true;
1869  if (zmq_errno() == EAGAIN)
1870  return false;
1871  throw error_t();
1872  }
1873 
1874 #ifdef ZMQ_HAS_RVALUE_REFS
1875  ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags")
1876  bool send(message_t &&msg_,
1877  int flags_ = 0) // default until removed
1878  {
1879 #ifdef ZMQ_CPP11
1880  return send(msg_, static_cast<send_flags>(flags_)).has_value();
1881 #else
1882  return send(msg_, flags_);
1883 #endif
1884  }
1885 #endif
1886 
1887 #ifdef ZMQ_CPP11
1888  send_result_t send(const_buffer buf, send_flags flags = send_flags::none)
1889  {
1890  const int nbytes =
1891  zmq_send(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1892  if (nbytes >= 0)
1893  return static_cast<size_t>(nbytes);
1894  if (zmq_errno() == EAGAIN)
1895  return {};
1896  throw error_t();
1897  }
1898 
1899  send_result_t send(message_t &msg, send_flags flags)
1900  {
1901  int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast<int>(flags));
1902  if (nbytes >= 0)
1903  return static_cast<size_t>(nbytes);
1904  if (zmq_errno() == EAGAIN)
1905  return {};
1906  throw error_t();
1907  }
1908 
1909  send_result_t send(message_t &&msg, send_flags flags)
1910  {
1911  return send(msg, flags);
1912  }
1913 #endif
1914 
1916  "from 4.3.1, use recv taking a mutable_buffer and recv_flags")
1917  size_t recv(void *buf_, size_t len_, int flags_ = 0)
1918  {
1919  int nbytes = zmq_recv(_handle, buf_, len_, flags_);
1920  if (nbytes >= 0)
1921  return static_cast<size_t>(nbytes);
1922  if (zmq_errno() == EAGAIN)
1923  return 0;
1924  throw error_t();
1925  }
1926 
1928  "from 4.3.1, use recv taking a reference to message_t and recv_flags")
1929  bool recv(message_t *msg_, int flags_ = 0)
1930  {
1931  int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_);
1932  if (nbytes >= 0)
1933  return true;
1934  if (zmq_errno() == EAGAIN)
1935  return false;
1936  throw error_t();
1937  }
1938 
1939 #ifdef ZMQ_CPP11
1941  recv_buffer_result_t recv(mutable_buffer buf,
1942  recv_flags flags = recv_flags::none)
1943  {
1944  const int nbytes =
1945  zmq_recv(_handle, buf.data(), buf.size(), static_cast<int>(flags));
1946  if (nbytes >= 0) {
1947  return recv_buffer_size{
1948  (std::min)(static_cast<size_t>(nbytes), buf.size()),
1949  static_cast<size_t>(nbytes)};
1950  }
1951  if (zmq_errno() == EAGAIN)
1952  return {};
1953  throw error_t();
1954  }
1955 
1957  recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none)
1958  {
1959  const int nbytes =
1960  zmq_msg_recv(msg.handle(), _handle, static_cast<int>(flags));
1961  if (nbytes >= 0) {
1962  assert(msg.size() == static_cast<size_t>(nbytes));
1963  return static_cast<size_t>(nbytes);
1964  }
1965  if (zmq_errno() == EAGAIN)
1966  return {};
1967  throw error_t();
1968  }
1969 #endif
1970 
1971 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
1972  void join(const char *group)
1973  {
1974  int rc = zmq_join(_handle, group);
1975  if (rc != 0)
1976  throw error_t();
1977  }
1978 
1979  void leave(const char *group)
1980  {
1981  int rc = zmq_leave(_handle, group);
1982  if (rc != 0)
1983  throw error_t();
1984  }
1985 #endif
1986 
1987  ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; }
1988  ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; }
1989 
1990  ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
1991  // note: non-const operator bool can be removed once
1992  // operator void* is removed from socket_t
1993  ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; }
1994 
1995  protected:
1996  void *_handle;
1997 
1998  private:
1999  void set_option(int option_, const void *optval_, size_t optvallen_)
2000  {
2001  int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_);
2002  if (rc != 0)
2003  throw error_t();
2004  }
2005 
2006  void get_option(int option_, void *optval_, size_t *optvallen_) const
2007  {
2008  int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_);
2009  if (rc != 0)
2010  throw error_t();
2011  }
2012 };
2013 } // namespace detail
2014 
2015 #ifdef ZMQ_CPP11
2016 enum class socket_type : int
2017 {
2018  req = ZMQ_REQ,
2019  rep = ZMQ_REP,
2020  dealer = ZMQ_DEALER,
2021  router = ZMQ_ROUTER,
2022  pub = ZMQ_PUB,
2023  sub = ZMQ_SUB,
2024  xpub = ZMQ_XPUB,
2025  xsub = ZMQ_XSUB,
2026  push = ZMQ_PUSH,
2027  pull = ZMQ_PULL,
2028 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
2029  server = ZMQ_SERVER,
2030  client = ZMQ_CLIENT,
2031  radio = ZMQ_RADIO,
2032  dish = ZMQ_DISH,
2033 #endif
2034 #if ZMQ_VERSION_MAJOR >= 4
2035  stream = ZMQ_STREAM,
2036 #endif
2037  pair = ZMQ_PAIR
2038 };
2039 #endif
2040 
2042 {
2043  struct _private
2044  {
2045  }; // disabling use other than with from_handle
2047 };
2048 
2051 
2052 // A non-owning nullable reference to a socket.
2053 // The reference is invalidated on socket close or destruction.
2055 {
2056  public:
2057  socket_ref() ZMQ_NOTHROW : detail::socket_base() {}
2058 #ifdef ZMQ_CPP11
2059  socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
2060 #endif
2061  socket_ref(from_handle_t /*fh*/, void *handle) ZMQ_NOTHROW
2062  : detail::socket_base(handle)
2063  {
2064  }
2065 };
2066 
2067 #ifdef ZMQ_CPP11
2068 inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2069 {
2070  return sr.handle() == nullptr;
2071 }
2072 inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2073 {
2074  return sr.handle() == nullptr;
2075 }
2076 inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2077 {
2078  return !(sr == nullptr);
2079 }
2080 inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2081 {
2082  return !(sr == nullptr);
2083 }
2084 #endif
2085 
2087 {
2088  return std::equal_to<const void *>()(a.handle(), b.handle());
2089 }
2091 {
2092  return !(a == b);
2093 }
2095 {
2096  return std::less<const void *>()(a.handle(), b.handle());
2097 }
2099 {
2100  return b < a;
2101 }
2103 {
2104  return !(a > b);
2105 }
2107 {
2108  return !(a < b);
2109 }
2110 
2111 } // namespace zmq
2112 
2113 #ifdef ZMQ_CPP11
2114 namespace std
2115 {
2116 template<> struct hash<zmq::socket_ref>
2117 {
2118  size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW
2119  {
2120  return hash<void *>()(sr.handle());
2121  }
2122 };
2123 } // namespace std
2124 #endif
2125 
2126 namespace zmq
2127 {
2129 {
2130  friend class monitor_t;
2131 
2132  public:
2133  socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {}
2134 
2135  socket_t(context_t &context_, int type_) :
2136  detail::socket_base(zmq_socket(context_.handle(), type_)),
2137  ctxptr(context_.handle())
2138  {
2139  if (_handle == ZMQ_NULLPTR)
2140  throw error_t();
2141  }
2142 
2143 #ifdef ZMQ_CPP11
2144  socket_t(context_t &context_, socket_type type_) :
2145  socket_t(context_, static_cast<int>(type_))
2146  {
2147  }
2148 #endif
2149 
2150 #ifdef ZMQ_HAS_RVALUE_REFS
2151  socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle),
2152  ctxptr(rhs.ctxptr)
2153  {
2154  rhs._handle = ZMQ_NULLPTR;
2155  rhs.ctxptr = ZMQ_NULLPTR;
2156  }
2157  socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW
2158  {
2159  close();
2160  std::swap(_handle, rhs._handle);
2161  std::swap(ctxptr, rhs.ctxptr);
2162  return *this;
2163  }
2164 #endif
2165 
2166  ~socket_t() ZMQ_NOTHROW { close(); }
2167 
2168  operator void *() ZMQ_NOTHROW { return _handle; }
2169 
2170  operator void const *() const ZMQ_NOTHROW { return _handle; }
2171 
2173  {
2174  if (_handle == ZMQ_NULLPTR)
2175  // already closed
2176  return;
2177  int rc = zmq_close(_handle);
2178  ZMQ_ASSERT(rc == 0);
2179  _handle = ZMQ_NULLPTR;
2180  ctxptr = ZMQ_NULLPTR;
2181  }
2182 
2184  {
2185  std::swap(_handle, other._handle);
2186  std::swap(ctxptr, other.ctxptr);
2187  }
2188 
2189  operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); }
2190 
2191  private:
2192  void *ctxptr;
2193 
2195  void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2196 
2197  // used by monitor_t
2198  socket_t(void *context_, int type_) :
2199  detail::socket_base(zmq_socket(context_, type_)), ctxptr(context_)
2200  {
2201  if (_handle == ZMQ_NULLPTR)
2202  throw error_t();
2203  if (ctxptr == ZMQ_NULLPTR)
2204  throw error_t();
2205  }
2206 };
2207 
2208 inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW
2209 {
2210  a.swap(b);
2211 }
2212 
2213 ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects")
2214 inline void proxy(void *frontend, void *backend, void *capture)
2215 {
2216  int rc = zmq_proxy(frontend, backend, capture);
2217  if (rc != 0)
2218  throw error_t();
2219 }
2220 
2221 inline void
2222 proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref())
2223 {
2224  int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle());
2225  if (rc != 0)
2226  throw error_t();
2227 }
2228 
2229 #ifdef ZMQ_HAS_PROXY_STEERABLE
2230 ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects")
2231 inline void
2232 proxy_steerable(void *frontend, void *backend, void *capture, void *control)
2233 {
2234  int rc = zmq_proxy_steerable(frontend, backend, capture, control);
2235  if (rc != 0)
2236  throw error_t();
2237 }
2238 
2239 inline void proxy_steerable(socket_ref frontend,
2240  socket_ref backend,
2241  socket_ref capture,
2242  socket_ref control)
2243 {
2244  int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(),
2245  capture.handle(), control.handle());
2246  if (rc != 0)
2247  throw error_t();
2248 }
2249 #endif
2250 
2252 {
2253  public:
2254  monitor_t() : _socket(), _monitor_socket() {}
2255 
2256  virtual ~monitor_t() { close(); }
2257 
2258 #ifdef ZMQ_HAS_RVALUE_REFS
2259  monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket()
2260  {
2261  std::swap(_socket, rhs._socket);
2262  std::swap(_monitor_socket, rhs._monitor_socket);
2263  }
2264 
2265  monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW
2266  {
2267  close();
2268  _socket = socket_ref();
2269  std::swap(_socket, rhs._socket);
2270  std::swap(_monitor_socket, rhs._monitor_socket);
2271  return *this;
2272  }
2273 #endif
2274 
2275 
2276  void
2277  monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2278  {
2279  monitor(socket, addr.c_str(), events);
2280  }
2281 
2282  void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2283  {
2284  init(socket, addr_, events);
2285  while (true) {
2286  check_event(-1);
2287  }
2288  }
2289 
2290  void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL)
2291  {
2292  init(socket, addr.c_str(), events);
2293  }
2294 
2295  void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL)
2296  {
2297  int rc = zmq_socket_monitor(socket.handle(), addr_, events);
2298  if (rc != 0)
2299  throw error_t();
2300 
2301  _socket = socket;
2302  _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR);
2303  _monitor_socket.connect(addr_);
2304 
2305  on_monitor_started();
2306  }
2307 
2308  bool check_event(int timeout = 0)
2309  {
2310  assert(_monitor_socket);
2311 
2312  zmq::message_t eventMsg;
2313 
2314  zmq::pollitem_t items[] = {
2315  {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0},
2316  };
2317 
2318  zmq::poll(&items[0], 1, timeout);
2319 
2320  if (items[0].revents & ZMQ_POLLIN) {
2321  int rc = zmq_msg_recv(eventMsg.handle(), _monitor_socket.handle(), 0);
2322  if (rc == -1 && zmq_errno() == ETERM)
2323  return false;
2324  assert(rc != -1);
2325 
2326  } else {
2327  return false;
2328  }
2329 
2330 #if ZMQ_VERSION_MAJOR >= 4
2331  const char *data = static_cast<const char *>(eventMsg.data());
2332  zmq_event_t msgEvent;
2333  memcpy(&msgEvent.event, data, sizeof(uint16_t));
2334  data += sizeof(uint16_t);
2335  memcpy(&msgEvent.value, data, sizeof(int32_t));
2336  zmq_event_t *event = &msgEvent;
2337 #else
2338  zmq_event_t *event = static_cast<zmq_event_t *>(eventMsg.data());
2339 #endif
2340 
2341 #ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT
2342  zmq::message_t addrMsg;
2343  int rc = zmq_msg_recv(addrMsg.handle(), _monitor_socket.handle(), 0);
2344  if (rc == -1 && zmq_errno() == ETERM) {
2345  return false;
2346  }
2347 
2348  assert(rc != -1);
2349  std::string address = addrMsg.to_string();
2350 #else
2351  // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types.
2352  std::string address = event->data.connected.addr;
2353 #endif
2354 
2355 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2356  if (event->event == ZMQ_EVENT_MONITOR_STOPPED) {
2357  return false;
2358  }
2359 
2360 #endif
2361 
2362  switch (event->event) {
2363  case ZMQ_EVENT_CONNECTED:
2364  on_event_connected(*event, address.c_str());
2365  break;
2366  case ZMQ_EVENT_CONNECT_DELAYED:
2367  on_event_connect_delayed(*event, address.c_str());
2368  break;
2369  case ZMQ_EVENT_CONNECT_RETRIED:
2370  on_event_connect_retried(*event, address.c_str());
2371  break;
2372  case ZMQ_EVENT_LISTENING:
2373  on_event_listening(*event, address.c_str());
2374  break;
2375  case ZMQ_EVENT_BIND_FAILED:
2376  on_event_bind_failed(*event, address.c_str());
2377  break;
2378  case ZMQ_EVENT_ACCEPTED:
2379  on_event_accepted(*event, address.c_str());
2380  break;
2381  case ZMQ_EVENT_ACCEPT_FAILED:
2382  on_event_accept_failed(*event, address.c_str());
2383  break;
2384  case ZMQ_EVENT_CLOSED:
2385  on_event_closed(*event, address.c_str());
2386  break;
2387  case ZMQ_EVENT_CLOSE_FAILED:
2388  on_event_close_failed(*event, address.c_str());
2389  break;
2390  case ZMQ_EVENT_DISCONNECTED:
2391  on_event_disconnected(*event, address.c_str());
2392  break;
2393 #ifdef ZMQ_BUILD_DRAFT_API
2394 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2395  case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL:
2396  on_event_handshake_failed_no_detail(*event, address.c_str());
2397  break;
2398  case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL:
2399  on_event_handshake_failed_protocol(*event, address.c_str());
2400  break;
2401  case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH:
2402  on_event_handshake_failed_auth(*event, address.c_str());
2403  break;
2404  case ZMQ_EVENT_HANDSHAKE_SUCCEEDED:
2405  on_event_handshake_succeeded(*event, address.c_str());
2406  break;
2407 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2408  case ZMQ_EVENT_HANDSHAKE_FAILED:
2409  on_event_handshake_failed(*event, address.c_str());
2410  break;
2411  case ZMQ_EVENT_HANDSHAKE_SUCCEED:
2412  on_event_handshake_succeed(*event, address.c_str());
2413  break;
2414 #endif
2415 #endif
2416  default:
2417  on_event_unknown(*event, address.c_str());
2418  break;
2419  }
2420 
2421  return true;
2422  }
2423 
2424 #ifdef ZMQ_EVENT_MONITOR_STOPPED
2425  void abort()
2426  {
2427  if (_socket)
2428  zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2429 
2430  _socket = socket_ref();
2431  }
2432 #endif
2433  virtual void on_monitor_started() {}
2434  virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
2435  {
2436  (void) event_;
2437  (void) addr_;
2438  }
2439  virtual void on_event_connect_delayed(const zmq_event_t &event_,
2440  const char *addr_)
2441  {
2442  (void) event_;
2443  (void) addr_;
2444  }
2445  virtual void on_event_connect_retried(const zmq_event_t &event_,
2446  const char *addr_)
2447  {
2448  (void) event_;
2449  (void) addr_;
2450  }
2451  virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
2452  {
2453  (void) event_;
2454  (void) addr_;
2455  }
2456  virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
2457  {
2458  (void) event_;
2459  (void) addr_;
2460  }
2461  virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
2462  {
2463  (void) event_;
2464  (void) addr_;
2465  }
2466  virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
2467  {
2468  (void) event_;
2469  (void) addr_;
2470  }
2471  virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
2472  {
2473  (void) event_;
2474  (void) addr_;
2475  }
2476  virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
2477  {
2478  (void) event_;
2479  (void) addr_;
2480  }
2481  virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
2482  {
2483  (void) event_;
2484  (void) addr_;
2485  }
2486 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2488  const char *addr_)
2489  {
2490  (void) event_;
2491  (void) addr_;
2492  }
2494  const char *addr_)
2495  {
2496  (void) event_;
2497  (void) addr_;
2498  }
2499  virtual void on_event_handshake_failed_auth(const zmq_event_t &event_,
2500  const char *addr_)
2501  {
2502  (void) event_;
2503  (void) addr_;
2504  }
2505  virtual void on_event_handshake_succeeded(const zmq_event_t &event_,
2506  const char *addr_)
2507  {
2508  (void) event_;
2509  (void) addr_;
2510  }
2511 #elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1)
2512  virtual void on_event_handshake_failed(const zmq_event_t &event_,
2513  const char *addr_)
2514  {
2515  (void) event_;
2516  (void) addr_;
2517  }
2518  virtual void on_event_handshake_succeed(const zmq_event_t &event_,
2519  const char *addr_)
2520  {
2521  (void) event_;
2522  (void) addr_;
2523  }
2524 #endif
2525  virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
2526  {
2527  (void) event_;
2528  (void) addr_;
2529  }
2530 
2531  private:
2533  void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION;
2534 
2537 
2539  {
2540  if (_socket)
2541  zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2542  _monitor_socket.close();
2543  }
2544 };
2545 
2546 #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2547 
2548 // polling events
2549 enum class event_flags : short
2550 {
2551  none = 0,
2552  pollin = ZMQ_POLLIN,
2553  pollout = ZMQ_POLLOUT,
2554  pollerr = ZMQ_POLLERR,
2555  pollpri = ZMQ_POLLPRI
2556 };
2557 
2558 constexpr event_flags operator|(event_flags a, event_flags b) noexcept
2559 {
2560  return detail::enum_bit_or(a, b);
2561 }
2562 constexpr event_flags operator&(event_flags a, event_flags b) noexcept
2563 {
2564  return detail::enum_bit_and(a, b);
2565 }
2566 constexpr event_flags operator^(event_flags a, event_flags b) noexcept
2567 {
2568  return detail::enum_bit_xor(a, b);
2569 }
2570 constexpr event_flags operator~(event_flags a) noexcept
2571 {
2572  return detail::enum_bit_not(a);
2573 }
2574 
2575 struct no_user_data;
2576 
2577 // layout compatible with zmq_poller_event_t
2578 template<class T = no_user_data> struct poller_event
2579 {
2580  socket_ref socket;
2581  ::zmq::fd_t fd;
2582  T *user_data;
2583  event_flags events;
2584 };
2585 
2586 template<typename T = no_user_data> class poller_t
2587 {
2588  public:
2589  using event_type = poller_event<T>;
2590 
2591  poller_t() : poller_ptr(zmq_poller_new())
2592  {
2593  if (!poller_ptr)
2594  throw error_t();
2595  }
2596 
2597  template<
2598  typename Dummy = void,
2599  typename =
2600  typename std::enable_if<!std::is_same<T, no_user_data>::value, Dummy>::type>
2601  void add(zmq::socket_ref socket, event_flags events, T *user_data)
2602  {
2603  add_impl(socket, events, user_data);
2604  }
2605 
2606  void add(zmq::socket_ref socket, event_flags events)
2607  {
2608  add_impl(socket, events, nullptr);
2609  }
2610 
2611  void remove(zmq::socket_ref socket)
2612  {
2613  if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) {
2614  throw error_t();
2615  }
2616  }
2617 
2618  void modify(zmq::socket_ref socket, event_flags events)
2619  {
2620  if (0
2621  != zmq_poller_modify(poller_ptr.get(), socket.handle(),
2622  static_cast<short>(events))) {
2623  throw error_t();
2624  }
2625  }
2626 
2627  size_t wait_all(std::vector<event_type> &poller_events,
2628  const std::chrono::milliseconds timeout)
2629  {
2630  int rc = zmq_poller_wait_all(
2631  poller_ptr.get(),
2632  reinterpret_cast<zmq_poller_event_t *>(poller_events.data()),
2633  static_cast<int>(poller_events.size()),
2634  static_cast<long>(timeout.count()));
2635  if (rc > 0)
2636  return static_cast<size_t>(rc);
2637 
2638 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3)
2639  if (zmq_errno() == EAGAIN)
2640 #else
2641  if (zmq_errno() == ETIMEDOUT)
2642 #endif
2643  return 0;
2644 
2645  throw error_t();
2646  }
2647 
2648 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 3)
2649  size_t size() const noexcept
2650  {
2651  int rc = zmq_poller_size(const_cast<void *>(poller_ptr.get()));
2652  ZMQ_ASSERT(rc >= 0);
2653  return static_cast<size_t>(std::max(rc, 0));
2654  }
2655 #endif
2656 
2657  private:
2658  struct destroy_poller_t
2659  {
2660  void operator()(void *ptr) noexcept
2661  {
2662  int rc = zmq_poller_destroy(&ptr);
2663  ZMQ_ASSERT(rc == 0);
2664  }
2665  };
2666 
2667  std::unique_ptr<void, destroy_poller_t> poller_ptr;
2668 
2669  void add_impl(zmq::socket_ref socket, event_flags events, T *user_data)
2670  {
2671  if (0
2672  != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data,
2673  static_cast<short>(events))) {
2674  throw error_t();
2675  }
2676  }
2677 };
2678 #endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2679 
2680 inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
2681 {
2682  return os << msg.str();
2683 }
2684 
2685 } // namespace zmq
2686 
2687 #endif // __ZMQ_HPP_INCLUDED__
2688 
void monitor(socket_t &socket, const char *addr_, int events=ZMQ_EVENT_ALL)
void swap(context_t &other) ZMQ_NOTHROW
const T * data(const std::vector< T, Alloc > &v)
Definition: flatbuffers.h:1108
#define ZMQ_DELETED_FUNCTION
context_t(int io_threads_, int max_sockets_=ZMQ_MAX_SOCKETS_DFLT)
ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private) ZMQ_NOTHROW
virtual const char * what() const ZMQ_NOTHROW ZMQ_OVERRIDE
ZMQ_NODISCARD const zmq_msg_t * handle() const ZMQ_NOTHROW
bool operator<(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
void monitor(socket_t &socket, std::string const &addr, int events=ZMQ_EVENT_ALL)
virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, const char *addr_)
#define ZMQ_OVERRIDE
zmq_pollitem_t pollitem_t
virtual void on_event_connect_delayed(const zmq_event_t &event_, const char *addr_)
static raw_event_t * buffer
Definition: minitrace.cpp:54
void close() ZMQ_NOTHROW
std::ostream & operator<<(std::ostream &os, const message_t &msg)
const char * gets(const char *property_)
#define ZMQ_EXPLICIT
void swap(socket_t &other) ZMQ_NOTHROW
void bind(const char *addr_)
T * data() ZMQ_NOTHROW
void get_option(int option_, void *optval_, size_t *optvallen_) const
virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
void rebuild(const void *data_, size_t size_)
message_t(const void *data_, size_t size_)
Definition: any.hpp:455
void swap(linb::any &lhs, linb::any &rhs) noexcept
Definition: any.hpp:457
ZMQ_NODISCARD void * handle() ZMQ_NOTHROW
#define ZMQ_ASSERT(expression)
std::string str() const
ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW
basic_string_view< CharT, Traits > to_string_view(std::basic_string< CharT, Traits, Allocator > const &s)
void unbind(std::string const &addr)
void disconnect(const char *addr_)
void close() ZMQ_NOTHROW
bool operator>=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
error_t() ZMQ_NOTHROW
#define ZMQ_NULLPTR
virtual void on_event_handshake_succeeded(const zmq_event_t &event_, const char *addr_)
ZMQ_NODISCARD zmq_msg_t * handle() ZMQ_NOTHROW
T const * data() const ZMQ_NOTHROW
~message_t() ZMQ_NOTHROW
ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW
void proxy_steerable(void *frontend, void *backend, void *capture, void *control)
void * data() ZMQ_NOTHROW
#define ZMQ_NODISCARD
#define ZMQ_CONSTEXPR_VAR
zmq_free_fn free_fn
int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_=-1)
void proxy(void *frontend, void *backend, void *capture)
virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, const char *addr_)
void move(message_t &msg_)
socket_t() ZMQ_NOTHROW
const void * data() const ZMQ_NOTHROW
void set_option(int option_, const void *optval_, size_t optvallen_)
#define ZMQ_NOTHROW
void copy(message_t &msg_)
#define ZMQ_CONSTEXPR_IF
void init(socket_t &socket, const char *addr_, int events=ZMQ_EVENT_ALL)
bool operator>(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
bool check_event(int timeout=0)
message_t(ForwardIter first, ForwardIter last)
virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, const char *addr_)
int num() const ZMQ_NOTHROW
message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_=ZMQ_NULLPTR)
#define ZMQ_CONSTEXPR_FN
~socket_t() ZMQ_NOTHROW
virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
socket_t(context_t &context_, int type_)
void rebuild(size_t size_)
bool operator<=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
message_t(size_t size_)
typename std::enable_if< Predicate::value >::type * enable_if
Definition: basic_types.h:168
bool operator==(const message_t &other) const ZMQ_NOTHROW
virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
void version(int *major_, int *minor_, int *patch_)
virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
void connect(std::string const &addr)
bool operator==(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
socket_ref(from_handle_t, void *handle) ZMQ_NOTHROW
bool operator!=(const message_t &other) const ZMQ_NOTHROW
void connect(const char *addr_)
void swap(message_t &a, message_t &b) ZMQ_NOTHROW
void shutdown() ZMQ_NOTHROW
size_t size() const ZMQ_NOTHROW
void bind(std::string const &addr)
void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_=ZMQ_NULLPTR)
bool operator!=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
virtual void on_monitor_started()
virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
void init(socket_t &socket, std::string const &addr, int events=ZMQ_EVENT_ALL)
#define ZMQ_CPP11_DEPRECATED(msg)
virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
message_t() ZMQ_NOTHROW
void disconnect(std::string const &addr)
~context_t() ZMQ_NOTHROW
void swap(message_t &other) ZMQ_NOTHROW
void close() ZMQ_NOTHROW
void unbind(const char *addr_)
std::string to_string() const
virtual void on_event_connect_retried(const zmq_event_t &event_, const char *addr_)
error_t(int err) ZMQ_NOTHROW
ZMQ_CONSTEXPR_VAR from_handle_t from_handle
bool more() const ZMQ_NOTHROW


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:25