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 #else
71 #define ZMQ_DEPRECATED(msg)
72 #endif
73 
74 #if defined(ZMQ_CPP17)
75 #define ZMQ_NODISCARD [[nodiscard]]
76 #else
77 #define ZMQ_NODISCARD
78 #endif
79 
80 #if defined(ZMQ_CPP11)
81 #define ZMQ_NOTHROW noexcept
82 #define ZMQ_EXPLICIT explicit
83 #define ZMQ_OVERRIDE override
84 #define ZMQ_NULLPTR nullptr
85 #define ZMQ_CONSTEXPR_FN constexpr
86 #define ZMQ_CONSTEXPR_VAR constexpr
87 #define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg)
88 #else
89 #define ZMQ_NOTHROW throw()
90 #define ZMQ_EXPLICIT
91 #define ZMQ_OVERRIDE
92 #define ZMQ_NULLPTR 0
93 #define ZMQ_CONSTEXPR_FN
94 #define ZMQ_CONSTEXPR_VAR const
95 #define ZMQ_CPP11_DEPRECATED(msg)
96 #endif
97 #if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900) && (!defined(__GNUC__) || __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3))
98 #define ZMQ_EXTENDED_CONSTEXPR
99 #endif
100 #if defined(ZMQ_CPP17)
101 #define ZMQ_INLINE_VAR inline
102 #define ZMQ_CONSTEXPR_IF constexpr
103 #else
104 #define ZMQ_INLINE_VAR
105 #define ZMQ_CONSTEXPR_IF
106 #endif
107 
108 #include <cassert>
109 #include <cstring>
110 
111 #include <algorithm>
112 #include <exception>
113 #include <iomanip>
114 #include <sstream>
115 #include <string>
116 #include <vector>
117 #ifdef ZMQ_CPP11
118 #include <array>
119 #include <chrono>
120 #include <tuple>
121 #include <memory>
122 #endif
123 
124 #if defined(__has_include) && defined(ZMQ_CPP17)
125 #define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X)
126 #else
127 #define CPPZMQ_HAS_INCLUDE_CPP17(X) 0
128 #endif
129 
130 #if CPPZMQ_HAS_INCLUDE_CPP17(<optional>) && !defined(CPPZMQ_HAS_OPTIONAL)
131 #define CPPZMQ_HAS_OPTIONAL 1
132 #endif
133 #ifndef CPPZMQ_HAS_OPTIONAL
134 #define CPPZMQ_HAS_OPTIONAL 0
135 #elif CPPZMQ_HAS_OPTIONAL
136 #include <optional>
137 #endif
138 
139 #if CPPZMQ_HAS_INCLUDE_CPP17(<string_view>) && !defined(CPPZMQ_HAS_STRING_VIEW)
140 #define CPPZMQ_HAS_STRING_VIEW 1
141 #endif
142 #ifndef CPPZMQ_HAS_STRING_VIEW
143 #define CPPZMQ_HAS_STRING_VIEW 0
144 #elif CPPZMQ_HAS_STRING_VIEW
145 #include <string_view>
146 #endif
147 
148 /* Version macros for compile-time API version detection */
149 #define CPPZMQ_VERSION_MAJOR 4
150 #define CPPZMQ_VERSION_MINOR 9
151 #define CPPZMQ_VERSION_PATCH 0
152 
153 #define CPPZMQ_VERSION \
154  ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \
155  CPPZMQ_VERSION_PATCH)
156 
157 // Detect whether the compiler supports C++11 rvalue references.
158 #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \
159  && defined(__GXX_EXPERIMENTAL_CXX0X__))
160 #define ZMQ_HAS_RVALUE_REFS
161 #define ZMQ_DELETED_FUNCTION = delete
162 #elif defined(__clang__)
163 #if __has_feature(cxx_rvalue_references)
164 #define ZMQ_HAS_RVALUE_REFS
165 #endif
166 
167 #if __has_feature(cxx_deleted_functions)
168 #define ZMQ_DELETED_FUNCTION = delete
169 #else
170 #define ZMQ_DELETED_FUNCTION
171 #endif
172 #elif defined(_MSC_VER) && (_MSC_VER >= 1900)
173 #define ZMQ_HAS_RVALUE_REFS
174 #define ZMQ_DELETED_FUNCTION = delete
175 #elif defined(_MSC_VER) && (_MSC_VER >= 1600)
176 #define ZMQ_HAS_RVALUE_REFS
177 #define ZMQ_DELETED_FUNCTION
178 #else
179 #define ZMQ_DELETED_FUNCTION
180 #endif
181 
182 #if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER) \
183  && defined(__GNUC__) && __GNUC__ < 5
184 #define ZMQ_CPP11_PARTIAL
185 #elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805
186 //the date here is the last date of gcc 4.9.4, which
187 // effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch
188 #define ZMQ_CPP11_PARTIAL
189 #endif
190 
191 #ifdef ZMQ_CPP11
192 #ifdef ZMQ_CPP11_PARTIAL
193 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T)
194 #else
195 #include <type_traits>
196 #define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
197 #endif
198 #endif
199 
200 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0)
201 #define ZMQ_NEW_MONITOR_EVENT_LAYOUT
202 #endif
203 
204 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
205 #define ZMQ_HAS_PROXY_STEERABLE
206 /* Socket event data */
207 typedef struct
208 {
209  uint16_t event; // id of the event as bitfield
210  int32_t value; // value is either error code, fd or reconnect interval
211 } zmq_event_t;
212 #endif
213 
214 // Avoid using deprecated message receive function when possible
215 #if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0)
216 #define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags)
217 #endif
218 
219 
220 // In order to prevent unused variable warnings when building in non-debug
221 // mode use this macro to make assertions.
222 #ifndef NDEBUG
223 #define ZMQ_ASSERT(expression) assert(expression)
224 #else
225 #define ZMQ_ASSERT(expression) (void) (expression)
226 #endif
227 
228 namespace zmq
229 {
230 #ifdef ZMQ_CPP11
231 namespace detail
232 {
233 namespace ranges
234 {
235 using std::begin;
236 using std::end;
237 template<class T> auto begin(T &&r) -> decltype(begin(std::forward<T>(r)))
238 {
239  return begin(std::forward<T>(r));
240 }
241 template<class T> auto end(T &&r) -> decltype(end(std::forward<T>(r)))
242 {
243  return end(std::forward<T>(r));
244 }
245 } // namespace ranges
246 
247 template<class T> using void_t = void;
248 
249 template<class Iter>
250 using iter_value_t = typename std::iterator_traits<Iter>::value_type;
251 
252 template<class Range>
253 using range_iter_t = decltype(
254  ranges::begin(std::declval<typename std::remove_reference<Range>::type &>()));
255 
256 template<class Range> using range_value_t = iter_value_t<range_iter_t<Range>>;
257 
258 template<class T, class = void> struct is_range : std::false_type
259 {
260 };
261 
262 template<class T>
263 struct is_range<
264  T,
265  void_t<decltype(
266  ranges::begin(std::declval<typename std::remove_reference<T>::type &>())
267  == ranges::end(std::declval<typename std::remove_reference<T>::type &>()))>>
268  : std::true_type
269 {
270 };
271 
272 } // namespace detail
273 #endif
274 
275 typedef zmq_free_fn free_fn;
276 typedef zmq_pollitem_t pollitem_t;
277 
278 // duplicate definition from libzmq 4.3.3
279 #if defined _WIN32
280 #if defined _WIN64
281 typedef unsigned __int64 fd_t;
282 #else
283 typedef unsigned int fd_t;
284 #endif
285 #else
286 typedef int fd_t;
287 #endif
288 
289 class error_t : public std::exception
290 {
291  public:
292  error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {}
293  explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {}
294  virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE
295  {
296  return zmq_strerror(errnum);
297  }
298  int num() const ZMQ_NOTHROW { return errnum; }
299 
300  private:
301  int errnum;
302 };
303 
304 namespace detail {
305 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
306 {
307  int rc = zmq_poll(items_, static_cast<int>(nitems_), timeout_);
308  if (rc < 0)
309  throw error_t();
310  return rc;
311 }
312 }
313 
314 #ifdef ZMQ_CPP11
315 ZMQ_DEPRECATED("from 4.8.0, use poll taking std::chrono::duration instead of long")
316 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
317 #else
318 inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1)
319 #endif
320 {
321  return detail::poll(items_, nitems_, timeout_);
322 }
323 
324 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
325 inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1)
326 {
327  return detail::poll(const_cast<zmq_pollitem_t *>(items_), nitems_, timeout_);
328 }
329 
330 #ifdef ZMQ_CPP11
331 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
332 inline int
333 poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout)
334 {
335  return detail::poll(const_cast<zmq_pollitem_t *>(items), nitems,
336  static_cast<long>(timeout.count()));
337 }
338 
339 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
340 inline int poll(std::vector<zmq_pollitem_t> const &items,
341  std::chrono::milliseconds timeout)
342 {
343  return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(),
344  static_cast<long>(timeout.count()));
345 }
346 
347 ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items")
348 inline int poll(std::vector<zmq_pollitem_t> const &items, long timeout_ = -1)
349 {
350  return detail::poll(const_cast<zmq_pollitem_t *>(items.data()), items.size(), timeout_);
351 }
352 
353 inline int
354 poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
355 {
356  return detail::poll(items, nitems, static_cast<long>(timeout.count()));
357 }
358 
359 inline int poll(std::vector<zmq_pollitem_t> &items,
360  std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
361 {
362  return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
363 }
364 
365 ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono::duration instead of long")
366 inline int poll(std::vector<zmq_pollitem_t> &items, long timeout_)
367 {
368  return detail::poll(items.data(), items.size(), timeout_);
369 }
370 
371 template<std::size_t SIZE>
372 inline int poll(std::array<zmq_pollitem_t, SIZE> &items,
373  std::chrono::milliseconds timeout = std::chrono::milliseconds{-1})
374 {
375  return detail::poll(items.data(), items.size(), static_cast<long>(timeout.count()));
376 }
377 #endif
378 
379 
380 inline void version(int *major_, int *minor_, int *patch_)
381 {
382  zmq_version(major_, minor_, patch_);
383 }
384 
385 #ifdef ZMQ_CPP11
386 inline std::tuple<int, int, int> version()
387 {
388  std::tuple<int, int, int> v;
389  zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v));
390  return v;
391 }
392 
393 #if !defined(ZMQ_CPP11_PARTIAL)
394 namespace detail
395 {
396 template<class T> struct is_char_type
397 {
398  // true if character type for string literals in C++11
399  static constexpr bool value =
402 };
403 }
404 #endif
405 
406 #endif
407 
409 {
410  public:
412  {
413  int rc = zmq_msg_init(&msg);
414  ZMQ_ASSERT(rc == 0);
415  }
416 
417  explicit message_t(size_t size_)
418  {
419  int rc = zmq_msg_init_size(&msg, size_);
420  if (rc != 0)
421  throw error_t();
422  }
423 
424  template<class ForwardIter> message_t(ForwardIter first, ForwardIter last)
425  {
426  typedef typename std::iterator_traits<ForwardIter>::value_type value_t;
427 
428  assert(std::distance(first, last) >= 0);
429  size_t const size_ =
430  static_cast<size_t>(std::distance(first, last)) * sizeof(value_t);
431  int const rc = zmq_msg_init_size(&msg, size_);
432  if (rc != 0)
433  throw error_t();
434  std::copy(first, last, data<value_t>());
435  }
436 
437  message_t(const void *data_, size_t size_)
438  {
439  int rc = zmq_msg_init_size(&msg, size_);
440  if (rc != 0)
441  throw error_t();
442  if (size_) {
443  // this constructor allows (nullptr, 0),
444  // memcpy with a null pointer is UB
445  memcpy(data(), data_, size_);
446  }
447  }
448 
449  message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
450  {
451  int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
452  if (rc != 0)
453  throw error_t();
454  }
455 
456  // overload set of string-like types and generic containers
457 #if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL)
458  // NOTE this constructor will include the null terminator
459  // when called with a string literal.
460  // An overload taking const char* can not be added because
461  // it would be preferred over this function and break compatiblity.
462  template<
463  class Char,
464  size_t N,
465  typename = typename std::enable_if<detail::is_char_type<Char>::value>::type>
466  ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) "
467  "or strings instead")
468  explicit message_t(const Char (&data)[N]) :
469  message_t(detail::ranges::begin(data), detail::ranges::end(data))
470  {
471  }
472 
473  template<class Range,
474  typename = typename std::enable_if<
476  && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t<Range>)
477  && !detail::is_char_type<detail::range_value_t<Range>>::value
479  explicit message_t(const Range &rng) :
480  message_t(detail::ranges::begin(rng), detail::ranges::end(rng))
481  {
482  }
483 
484  explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {}
485 
486 #if CPPZMQ_HAS_STRING_VIEW
487  explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {}
488 #endif
489 
490 #endif
491 
492 #ifdef ZMQ_HAS_RVALUE_REFS
493  message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg)
494  {
495  int rc = zmq_msg_init(&rhs.msg);
496  ZMQ_ASSERT(rc == 0);
497  }
498 
500  {
501  std::swap(msg, rhs.msg);
502  return *this;
503  }
504 #endif
505 
507  {
508  int rc = zmq_msg_close(&msg);
509  ZMQ_ASSERT(rc == 0);
510  }
511 
512  void rebuild()
513  {
514  int rc = zmq_msg_close(&msg);
515  if (rc != 0)
516  throw error_t();
517  rc = zmq_msg_init(&msg);
518  ZMQ_ASSERT(rc == 0);
519  }
520 
521  void rebuild(size_t size_)
522  {
523  int rc = zmq_msg_close(&msg);
524  if (rc != 0)
525  throw error_t();
526  rc = zmq_msg_init_size(&msg, size_);
527  if (rc != 0)
528  throw error_t();
529  }
530 
531  void rebuild(const void *data_, size_t size_)
532  {
533  int rc = zmq_msg_close(&msg);
534  if (rc != 0)
535  throw error_t();
536  rc = zmq_msg_init_size(&msg, size_);
537  if (rc != 0)
538  throw error_t();
539  memcpy(data(), data_, size_);
540  }
541 
542  void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR)
543  {
544  int rc = zmq_msg_close(&msg);
545  if (rc != 0)
546  throw error_t();
547  rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_);
548  if (rc != 0)
549  throw error_t();
550  }
551 
552  ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead")
553  void move(message_t const *msg_)
554  {
555  int rc = zmq_msg_move(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
556  if (rc != 0)
557  throw error_t();
558  }
559 
560  void move(message_t &msg_)
561  {
562  int rc = zmq_msg_move(&msg, msg_.handle());
563  if (rc != 0)
564  throw error_t();
565  }
566 
567  ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead")
568  void copy(message_t const *msg_)
569  {
570  int rc = zmq_msg_copy(&msg, const_cast<zmq_msg_t *>(msg_->handle()));
571  if (rc != 0)
572  throw error_t();
573  }
574 
575  void copy(message_t &msg_)
576  {
577  int rc = zmq_msg_copy(&msg, msg_.handle());
578  if (rc != 0)
579  throw error_t();
580  }
581 
582  bool more() const ZMQ_NOTHROW
583  {
584  int rc = zmq_msg_more(const_cast<zmq_msg_t *>(&msg));
585  return rc != 0;
586  }
587 
588  void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); }
589 
590  const void *data() const ZMQ_NOTHROW
591  {
592  return zmq_msg_data(const_cast<zmq_msg_t *>(&msg));
593  }
594 
595  size_t size() const ZMQ_NOTHROW
596  {
597  return zmq_msg_size(const_cast<zmq_msg_t *>(&msg));
598  }
599 
600  ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; }
601 
602  template<typename T> T *data() ZMQ_NOTHROW { return static_cast<T *>(data()); }
603 
604  template<typename T> T const *data() const ZMQ_NOTHROW
605  {
606  return static_cast<T const *>(data());
607  }
608 
609  ZMQ_DEPRECATED("from 4.3.0, use operator== instead")
610  bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; }
611 
612  bool operator==(const message_t &other) const ZMQ_NOTHROW
613  {
614  const size_t my_size = size();
615  return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size);
616  }
617 
618  bool operator!=(const message_t &other) const ZMQ_NOTHROW
619  {
620  return !(*this == other);
621  }
622 
623 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0)
624  int get(int property_)
625  {
626  int value = zmq_msg_get(&msg, property_);
627  if (value == -1)
628  throw error_t();
629  return value;
630  }
631 #endif
632 
633 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0)
634  const char *gets(const char *property_)
635  {
636  const char *value = zmq_msg_gets(&msg, property_);
637  if (value == ZMQ_NULLPTR)
638  throw error_t();
639  return value;
640  }
641 #endif
642 
643 #if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
644  uint32_t routing_id() const
645  {
646  return zmq_msg_routing_id(const_cast<zmq_msg_t *>(&msg));
647  }
648 
649  void set_routing_id(uint32_t routing_id)
650  {
651  int rc = zmq_msg_set_routing_id(&msg, routing_id);
652  if (rc != 0)
653  throw error_t();
654  }
655 
656  const char *group() const
657  {
658  return zmq_msg_group(const_cast<zmq_msg_t *>(&msg));
659  }
660 
661  void set_group(const char *group)
662  {
663  int rc = zmq_msg_set_group(&msg, group);
664  if (rc != 0)
665  throw error_t();
666  }
667 #endif
668 
669  // interpret message content as a string
670  std::string to_string() const
671  {
672  return std::string(static_cast<const char *>(data()), size());
673  }
674 #if CPPZMQ_HAS_STRING_VIEW
675  // interpret message content as a string
676  std::string_view to_string_view() const noexcept
677  {
678  return std::string_view(static_cast<const char *>(data()), size());
679  }
680 #endif
681 
688  std::string str() const
689  {
690  // Partly mutuated from the same method in zmq::multipart_t
691  std::stringstream os;
692 
693  const unsigned char *msg_data = this->data<unsigned char>();
694  unsigned char byte;
695  size_t size = this->size();
696  int is_ascii[2] = {0, 0};
697 
698  os << "zmq::message_t [size " << std::dec << std::setw(3)
699  << std::setfill('0') << size << "] (";
700  // Totally arbitrary
701  if (size >= 1000) {
702  os << "... too big to print)";
703  } else {
704  while (size--) {
705  byte = *msg_data++;
706 
707  is_ascii[1] = (byte >= 32 && byte < 127);
708  if (is_ascii[1] != is_ascii[0])
709  os << " "; // Separate text/non text
710 
711  if (is_ascii[1]) {
712  os << byte;
713  } else {
714  os << std::hex << std::uppercase << std::setw(2)
715  << std::setfill('0') << static_cast<short>(byte);
716  }
717  is_ascii[0] = is_ascii[1];
718  }
719  os << ")";
720  }
721  return os.str();
722  }
723 
725  {
726  // this assumes zmq::msg_t from libzmq is trivially relocatable
727  std::swap(msg, other.msg);
728  }
729 
730  ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; }
731  ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; }
732 
733  private:
734  // The underlying message
735  zmq_msg_t msg;
736 
737  // Disable implicit message copying, so that users won't use shared
738  // messages (less efficient) without being aware of the fact.
741 };
742 
743 inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW
744 {
745  a.swap(b);
746 }
747 
748 #ifdef ZMQ_CPP11
749 enum class ctxopt
750 {
751 #ifdef ZMQ_BLOCKY
752  blocky = ZMQ_BLOCKY,
753 #endif
754 #ifdef ZMQ_IO_THREADS
755  io_threads = ZMQ_IO_THREADS,
756 #endif
757 #ifdef ZMQ_THREAD_SCHED_POLICY
758  thread_sched_policy = ZMQ_THREAD_SCHED_POLICY,
759 #endif
760 #ifdef ZMQ_THREAD_PRIORITY
761  thread_priority = ZMQ_THREAD_PRIORITY,
762 #endif
763 #ifdef ZMQ_THREAD_AFFINITY_CPU_ADD
764  thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD,
765 #endif
766 #ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE
767  thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE,
768 #endif
769 #ifdef ZMQ_THREAD_NAME_PREFIX
770  thread_name_prefix = ZMQ_THREAD_NAME_PREFIX,
771 #endif
772 #ifdef ZMQ_MAX_MSGSZ
773  max_msgsz = ZMQ_MAX_MSGSZ,
774 #endif
775 #ifdef ZMQ_ZERO_COPY_RECV
776  zero_copy_recv = ZMQ_ZERO_COPY_RECV,
777 #endif
778 #ifdef ZMQ_MAX_SOCKETS
779  max_sockets = ZMQ_MAX_SOCKETS,
780 #endif
781 #ifdef ZMQ_SOCKET_LIMIT
782  socket_limit = ZMQ_SOCKET_LIMIT,
783 #endif
784 #ifdef ZMQ_IPV6
785  ipv6 = ZMQ_IPV6,
786 #endif
787 #ifdef ZMQ_MSG_T_SIZE
788  msg_t_size = ZMQ_MSG_T_SIZE
789 #endif
790 };
791 #endif
792 
794 {
795  public:
797  {
798  ptr = zmq_ctx_new();
799  if (ptr == ZMQ_NULLPTR)
800  throw error_t();
801  }
802 
803 
804  explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT)
805  {
806  ptr = zmq_ctx_new();
807  if (ptr == ZMQ_NULLPTR)
808  throw error_t();
809 
810  int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_);
811  ZMQ_ASSERT(rc == 0);
812 
813  rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_);
814  ZMQ_ASSERT(rc == 0);
815  }
816 
817 #ifdef ZMQ_HAS_RVALUE_REFS
818  context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; }
820  {
821  close();
822  std::swap(ptr, rhs.ptr);
823  return *this;
824  }
825 #endif
826 
828 
829  ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead")
830  int setctxopt(int option_, int optval_)
831  {
832  int rc = zmq_ctx_set(ptr, option_, optval_);
833  ZMQ_ASSERT(rc == 0);
834  return rc;
835  }
836 
837  ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead")
838  int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); }
839 
840 #ifdef ZMQ_CPP11
841  void set(ctxopt option, int optval)
842  {
843  int rc = zmq_ctx_set(ptr, static_cast<int>(option), optval);
844  if (rc == -1)
845  throw error_t();
846  }
847 
848  ZMQ_NODISCARD int get(ctxopt option)
849  {
850  int rc = zmq_ctx_get(ptr, static_cast<int>(option));
851  // some options have a default value of -1
852  // which is unfortunate, and may result in errors
853  // that don't make sense
854  if (rc == -1)
855  throw error_t();
856  return rc;
857  }
858 #endif
859 
860  // Terminates context (see also shutdown()).
862  {
863  if (ptr == ZMQ_NULLPTR)
864  return;
865 
866  int rc;
867  do {
868  rc = zmq_ctx_term(ptr);
869  } while (rc == -1 && errno == EINTR);
870 
871  ZMQ_ASSERT(rc == 0);
872  ptr = ZMQ_NULLPTR;
873  }
874 
875  // Shutdown context in preparation for termination (close()).
876  // Causes all blocking socket operations and any further
877  // socket operations to return with ETERM.
879  {
880  if (ptr == ZMQ_NULLPTR)
881  return;
882  int rc = zmq_ctx_shutdown(ptr);
883  ZMQ_ASSERT(rc == 0);
884  }
885 
886  // Be careful with this, it's probably only useful for
887  // using the C api together with an existing C++ api.
888  // Normally you should never need to use this.
889  ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; }
890 
891  ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; }
892 
893  ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; }
894 
895  ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead")
896  operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; }
897 
898  void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); }
899 
900  private:
901  void *ptr;
902 
905 };
906 
907 inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW
908 {
909  a.swap(b);
910 }
911 
912 #ifdef ZMQ_CPP11
913 
914 struct recv_buffer_size
915 {
916  size_t size; // number of bytes written to buffer
917  size_t untruncated_size; // untruncated message size in bytes
918 
919  ZMQ_NODISCARD bool truncated() const noexcept
920  {
921  return size != untruncated_size;
922  }
923 };
924 
925 #if CPPZMQ_HAS_OPTIONAL
926 
927 using send_result_t = std::optional<size_t>;
928 using recv_result_t = std::optional<size_t>;
929 using recv_buffer_result_t = std::optional<recv_buffer_size>;
930 
931 #else
932 
933 namespace detail
934 {
935 // A C++11 type emulating the most basic
936 // operations of std::optional for trivial types
937 template<class T> class trivial_optional
938 {
939  public:
940  static_assert(std::is_trivial<T>::value, "T must be trivial");
941  using value_type = T;
942 
943  trivial_optional() = default;
944  trivial_optional(T value) noexcept : _value(value), _has_value(true) {}
945 
946  const T *operator->() const noexcept
947  {
948  assert(_has_value);
949  return &_value;
950  }
951  T *operator->() noexcept
952  {
953  assert(_has_value);
954  return &_value;
955  }
956 
957  const T &operator*() const noexcept
958  {
959  assert(_has_value);
960  return _value;
961  }
962  T &operator*() noexcept
963  {
964  assert(_has_value);
965  return _value;
966  }
967 
968  T &value()
969  {
970  if (!_has_value)
971  throw std::exception();
972  return _value;
973  }
974  const T &value() const
975  {
976  if (!_has_value)
977  throw std::exception();
978  return _value;
979  }
980 
981  explicit operator bool() const noexcept { return _has_value; }
982  bool has_value() const noexcept { return _has_value; }
983 
984  private:
985  T _value{};
986  bool _has_value{false};
987 };
988 } // namespace detail
989 
990 using send_result_t = detail::trivial_optional<size_t>;
991 using recv_result_t = detail::trivial_optional<size_t>;
992 using recv_buffer_result_t = detail::trivial_optional<recv_buffer_size>;
993 
994 #endif
995 
996 namespace detail
997 {
998 template<class T> constexpr T enum_bit_or(T a, T b) noexcept
999 {
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 } // namespace detail
1023 
1024 // partially satisfies named requirement BitmaskType
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 // partially satisfies named requirement BitmaskType
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 // mutable_buffer, const_buffer and buffer are based on
1075 // the Networking TS specification, draft:
1076 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf
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  // (std::min) is a workaround for when a min macro is defined
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 // buffer creation
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 =
1189 };
1190 
1191 template<class T> struct is_pod_like
1192 {
1193  // NOTE: The networking draft N4771 section 16.11 requires
1194  // T in the buffer functions below to be
1195  // trivially copyable OR standard layout.
1196  // Here we decide to be conservative and require both.
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 (&/*array*/)[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 } // namespace detail
1237 
1238 // C array
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 // std::array
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 // std::vector
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 // std::basic_string
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 // std::basic_string_view
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 // Buffer for a string literal (null terminated)
1347 // where the buffer size excludes the terminating character.
1348 // Equivalent to zmq::buffer(std::string_view("...")).
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 // There are two types of options,
1415 // integral type with known compiler time size (int, bool, int64_t, uint64_t)
1416 // and arrays with dynamic size (strings, binary data).
1417 
1418 // BoolUnit: if true accepts values of type bool (but passed as T into libzmq)
1419 template<int Opt, class T, bool BoolUnit = false> struct integral_option
1420 {
1421 };
1422 
1423 // NullTerm:
1424 // 0: binary data
1425 // 1: null-terminated string (`getsockopt` size includes null)
1426 // 2: binary (size 32) or Z85 encoder string of size 41 (null included)
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 // deprecated, use zmq::fd_t
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 // ZMQ_CPP11
1657 #endif // ZMQ_TYPE
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 } // namespace sockopt
1696 #endif // ZMQ_CPP11
1697 
1698 
1699 namespace detail
1700 {
1702 {
1703  public:
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  // Set integral socket option, e.g.
1742  // `socket.set(zmq::sockopt::linger, 0)`
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  // Set integral socket option from boolean, e.g.
1751  // `socket.set(zmq::sockopt::immediate, false)`
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  // Set array socket option, e.g.
1761  // `socket.set(zmq::sockopt::plain_username, "foo123")`
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  // Set array socket option, e.g.
1769  // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))`
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  // Set array socket option, e.g.
1777  // `socket.set(zmq::sockopt::routing_id, id_str)`
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  // Set array socket option, e.g.
1786  // `socket.set(zmq::sockopt::routing_id, id_str)`
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  // Get scalar socket option, e.g.
1795  // `auto opt = socket.get(zmq::sockopt::linger)`
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  // Get array socket option, writes to buf, returns option size in bytes, e.g.
1808  // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))`
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  // Get array socket option as string (initializes the string buffer size to init_size) e.g.
1819  // `auto s = socket.get(zmq::sockopt::routing_id)`
1820  // Note: removes the null character from null-terminated string options,
1821  // i.e. the string size excludes the null character.
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; // get as Z85 string
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) // default until removed
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>
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) // default until removed
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 
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 
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
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 
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  // note: non-const operator bool can be removed once
2045  // operator void* is removed from socket_t
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 } // namespace detail
2067 
2069 {
2070  struct _private
2071  {
2072  }; // disabling use other than with from_handle
2074 };
2075 
2078 
2079 // A non-owning nullable reference to a socket.
2080 // The reference is invalidated on socket close or destruction.
2082 {
2083  public:
2085 #ifdef ZMQ_CPP11
2086  socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {}
2087 #endif
2088  socket_ref(from_handle_t /*fh*/, 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 /*p*/) ZMQ_NOTHROW
2096 {
2097  return sr.handle() == nullptr;
2098 }
2099 inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2100 {
2101  return sr.handle() == nullptr;
2102 }
2103 inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW
2104 {
2105  return !(sr == nullptr);
2106 }
2107 inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW
2108 {
2109  return !(sr == nullptr);
2110 }
2111 #endif
2112 
2114 {
2115  return std::equal_to<const void *>()(a.handle(), b.handle());
2116 }
2118 {
2119  return !(a == b);
2120 }
2122 {
2123  return std::less<const void *>()(a.handle(), b.handle());
2124 }
2126 {
2127  return b < a;
2128 }
2130 {
2131  return !(a > b);
2132 }
2134 {
2135  return !(a < b);
2136 }
2137 
2138 } // namespace zmq
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 } // namespace std
2151 #endif
2152 
2153 namespace zmq
2154 {
2156 {
2157  friend class monitor_t;
2158 
2159  public:
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  }
2185  {
2186  close();
2187  std::swap(_handle, rhs._handle);
2188  std::swap(ctxptr, rhs.ctxptr);
2189  return *this;
2190  }
2191 #endif
2192 
2194 
2195  operator void *() ZMQ_NOTHROW { return _handle; }
2196 
2197  operator void const *() const ZMQ_NOTHROW { return _handle; }
2198 
2200  {
2201  if (_handle == ZMQ_NULLPTR)
2202  // already closed
2203  return;
2204  int rc = zmq_close(_handle);
2205  ZMQ_ASSERT(rc == 0);
2206  _handle = ZMQ_NULLPTR;
2207  ctxptr = ZMQ_NULLPTR;
2208  }
2209 
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 
2222  void operator=(const socket_t &) ZMQ_DELETED_FUNCTION;
2223 
2224  // used by monitor_t
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
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,
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 
2279 {
2280  public:
2282 
2283  virtual ~monitor_t() { close(); }
2284 
2285 #ifdef ZMQ_HAS_RVALUE_REFS
2287  {
2288  std::swap(_socket, rhs._socket);
2289  std::swap(_monitor_socket, rhs._monitor_socket);
2290  }
2291 
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 
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  // 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.
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)
2517  const char *addr_)
2518  {
2519  (void) event_;
2520  (void) addr_;
2521  }
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:
2563 
2566 
2568  {
2569  if (_socket)
2570  zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0);
2572  }
2573 };
2574 
2575 #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2576 
2577 // polling events
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 // layout compatible with zmq_poller_event_t
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 =
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 // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
2708 
2709 inline std::ostream &operator<<(std::ostream &os, const message_t &msg)
2710 {
2711  return os << msg.str();
2712 }
2713 
2714 } // namespace zmq
2715 
2716 #endif // __ZMQ_HPP_INCLUDED__
zmq_event_t
Definition: 3rdparty/cppzmq/zmq.hpp:207
cx::size
constexpr auto size(const C &c) -> decltype(c.size())
Definition: wildcards.hpp:636
ZMQ_CONSTEXPR_VAR
#define ZMQ_CONSTEXPR_VAR
Definition: 3rdparty/cppzmq/zmq.hpp:94
zmq::monitor_t::on_monitor_started
virtual void on_monitor_started()
Definition: 3rdparty/cppzmq/zmq.hpp:2462
BT::enable_if
typename std::enable_if< Predicate::value >::type * enable_if
Definition: basic_types.h:305
zmq::message_t::handle
const ZMQ_NODISCARD zmq_msg_t * handle() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:731
zmq::socket_t::ctxptr
void * ctxptr
Definition: 3rdparty/cppzmq/zmq.hpp:2219
zmq::swap
void swap(message_t &a, message_t &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:743
zmq::poll
int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_=-1)
Definition: 3rdparty/cppzmq/zmq.hpp:318
zmq::monitor_t::on_event_handshake_failed_auth
virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2528
zmq::message_t::move
void move(message_t &msg_)
Definition: 3rdparty/cppzmq/zmq.hpp:560
zmq::message_t
Definition: 3rdparty/cppzmq/zmq.hpp:408
zmq::from_handle_t
Definition: 3rdparty/cppzmq/zmq.hpp:2068
zmq::message_t::data
const T * data() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:604
zmq::proxy
void proxy(void *frontend, void *backend, void *capture)
Definition: 3rdparty/cppzmq/zmq.hpp:2241
lexy::_unicode_db::uppercase
@ uppercase
Definition: unicode_database.hpp:72
zmq::monitor_t::monitor
void monitor(socket_t &socket, std::string const &addr, int events=ZMQ_EVENT_ALL)
Definition: 3rdparty/cppzmq/zmq.hpp:2304
zmq::detail::socket_base::connected
bool connected() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:1887
zmq::socket_t::swap
void swap(socket_t &other) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2210
zmq::context_t::context_t
context_t()
Definition: 3rdparty/cppzmq/zmq.hpp:796
zmq::monitor_t::on_event_handshake_failed_no_detail
virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2516
zmq::monitor_t::on_event_unknown
virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2554
zmq::from_handle_t::from_handle_t
ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2073
zmq::monitor_t::on_event_bind_failed
virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2485
zmq::pollitem_t
zmq_pollitem_t pollitem_t
Definition: 3rdparty/cppzmq/zmq.hpp:276
zmq::message_t::copy
void copy(message_t const *msg_)
Definition: 3rdparty/cppzmq/zmq.hpp:568
zmq::monitor_t::~monitor_t
virtual ~monitor_t()
Definition: 3rdparty/cppzmq/zmq.hpp:2283
zmq::message_t::to_string
std::string to_string() const
Definition: 3rdparty/cppzmq/zmq.hpp:670
zmq::context_t::operator=
void operator=(const context_t &) ZMQ_DELETED_FUNCTION
zmq::context_t::setctxopt
int setctxopt(int option_, int optval_)
Definition: 3rdparty/cppzmq/zmq.hpp:830
zmq::message_t::handle
ZMQ_NODISCARD zmq_msg_t * handle() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:730
literals
Definition: json.hpp:24461
detail::is_range
Definition: json.hpp:3725
zmq::socket_t
Definition: 3rdparty/cppzmq/zmq.hpp:2155
zmq::context_t::swap
void swap(context_t &other) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:898
zmq::error_t::errnum
int errnum
Definition: 3rdparty/cppzmq/zmq.hpp:301
zmq::message_t::data
void * data() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:588
zmq::socket_t::socket_t
socket_t(void *context_, int type_)
Definition: 3rdparty/cppzmq/zmq.hpp:2225
zmq::monitor_t::on_event_disconnected
virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2510
zmq::operator>
bool operator>(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2125
ZMQ_NOTHROW
#define ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:89
zmq::monitor_t::monitor_t
monitor_t()
Definition: 3rdparty/cppzmq/zmq.hpp:2281
zmq::message_t::data
const void * data() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:590
zmq::from_handle
ZMQ_CONSTEXPR_VAR from_handle_t from_handle
Definition: 3rdparty/cppzmq/zmq.hpp:2076
zmq::detail::socket_base::ZMQ_CPP11_DEPRECATED
ZMQ_CPP11_DEPRECATED("from 4.4.1, use send taking message_t or buffer (for contiguous " "ranges), and send_flags") bool send(T first
zmq::monitor_t::on_event_accept_failed
virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2495
zmq::detail::socket_base::bind
void bind(const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:1852
zmq::detail::socket_base::setsockopt
void setsockopt(int option_, T const &optval)
Definition: 3rdparty/cppzmq/zmq.hpp:1709
zmq::monitor_t::monitor
void monitor(socket_t &socket, const char *addr_, int events=ZMQ_EVENT_ALL)
Definition: 3rdparty/cppzmq/zmq.hpp:2309
zmq::message_t::more
bool more() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:582
zmq::monitor_t::on_event_listening
virtual void on_event_listening(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2480
zmq::message_t::swap
void swap(message_t &other) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:724
detail
detail namespace with internal helper functions
Definition: json.hpp:248
zmq::detail::socket_base::unbind
void unbind(std::string const &addr)
Definition: 3rdparty/cppzmq/zmq.hpp:1859
zmq::operator<
bool operator<(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2121
zmq::monitor_t::check_event
bool check_event(int timeout=0)
Definition: 3rdparty/cppzmq/zmq.hpp:2335
zmq::operator>=
bool operator>=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2133
zmq::error_t::error_t
error_t() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:292
magic_enum::bitwise_operators::operator^
constexpr E operator^(E lhs, E rhs) noexcept
Definition: magic_enum.hpp:1437
ZMQ_DEPRECATED
#define ZMQ_DEPRECATED(msg)
Definition: 3rdparty/cppzmq/zmq.hpp:71
zmq::message_t::message_t
message_t(size_t size_)
Definition: 3rdparty/cppzmq/zmq.hpp:417
zmq::detail::socket_base::send
size_t send(const void *buf_, size_t len_, int flags_=0)
Definition: 3rdparty/cppzmq/zmq.hpp:1890
zmq::message_t::equal
bool equal(const message_t *other) const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:610
zmq::detail::socket_base::socket_base
ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:1705
lexyd::hex
_d< 16 > hex
Definition: digit.hpp:237
magic_enum::detail::value
constexpr E value(std::size_t i) noexcept
Definition: magic_enum.hpp:664
zmq::socket_t::operator=
void operator=(const socket_t &) ZMQ_DELETED_FUNCTION
ZMQ_NODISCARD
#define ZMQ_NODISCARD
Definition: 3rdparty/cppzmq/zmq.hpp:77
zmq::operator==
bool operator==(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2113
zmq::context_t::close
void close() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:861
zmq::socket_ref
Definition: 3rdparty/cppzmq/zmq.hpp:2081
zmq::detail::socket_base::disconnect
void disconnect(const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:1879
zmq::message_t::message_t
message_t(ForwardIter first, ForwardIter last)
Definition: 3rdparty/cppzmq/zmq.hpp:424
cx::end
constexpr auto end(const C &c) -> decltype(c.end())
Definition: wildcards.hpp:686
detail::void
j template void())
Definition: json.hpp:4893
zmq::monitor_t::init
void init(socket_t &socket, std::string const &addr, int events=ZMQ_EVENT_ALL)
Definition: 3rdparty/cppzmq/zmq.hpp:2317
lexy::operator|
constexpr auto operator|(First first, Second second)
Composes two callbacks.
Definition: composition.hpp:100
zmq
Definition: 3rdparty/cppzmq/zmq.hpp:228
zmq::context_t
Definition: 3rdparty/cppzmq/zmq.hpp:793
ZMQ_ASSERT
#define ZMQ_ASSERT(expression)
Definition: 3rdparty/cppzmq/zmq.hpp:223
zmq::detail::socket_base::set_option
void set_option(int option_, const void *optval_, size_t optvallen_)
Definition: 3rdparty/cppzmq/zmq.hpp:2052
zmq::message_t::get
int get(int property_)
Definition: 3rdparty/cppzmq/zmq.hpp:624
zmq_event_t::event
uint16_t event
Definition: 3rdparty/cppzmq/zmq.hpp:209
ZMQ_OVERRIDE
#define ZMQ_OVERRIDE
Definition: 3rdparty/cppzmq/zmq.hpp:91
zmq::context_t::handle
ZMQ_NODISCARD void * handle() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:893
zmq::detail::socket_base::last
T last
Definition: 3rdparty/cppzmq/zmq.hpp:1916
ZMQ_CONSTEXPR_IF
#define ZMQ_CONSTEXPR_IF
Definition: 3rdparty/cppzmq/zmq.hpp:105
zmq::monitor_t::on_event_handshake_failed_protocol
virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2522
zmq::operator<<
std::ostream & operator<<(std::ostream &os, const message_t &msg)
Definition: 3rdparty/cppzmq/zmq.hpp:2709
lexy::_detail::void_t
void void_t
Definition: detect.hpp:12
detail::range_value_t
value_type_t< iterator_traits< iterator_t< T > >> range_value_t
Definition: json.hpp:3747
zmq::version
void version(int *major_, int *minor_, int *patch_)
Definition: 3rdparty/cppzmq/zmq.hpp:380
zmq::error_t::num
int num() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:298
zmq::context_t::ptr
void * ptr
Definition: 3rdparty/cppzmq/zmq.hpp:901
lexy::buffer
buffer(const CharT *, const CharT *) -> buffer< deduce_encoding< CharT >>
zmq::message_t::operator!=
bool operator!=(const message_t &other) const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:618
zmq::monitor_t::_socket
socket_ref _socket
Definition: 3rdparty/cppzmq/zmq.hpp:2564
zmq::socket_ref::socket_ref
socket_ref(from_handle_t, void *handle) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2088
zmq::fd_t
int fd_t
Definition: 3rdparty/cppzmq/zmq.hpp:286
zmq::detail::poll
int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_)
Definition: 3rdparty/cppzmq/zmq.hpp:305
zmq::message_t::gets
const char * gets(const char *property_)
Definition: 3rdparty/cppzmq/zmq.hpp:634
ZMQ_DELETED_FUNCTION
#define ZMQ_DELETED_FUNCTION
Definition: 3rdparty/cppzmq/zmq.hpp:179
zmq::socket_t::close
void close() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2199
zmq::monitor_t::on_event_close_failed
virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2505
zmq::context_t::shutdown
void shutdown() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:878
zmq::monitor_t::on_event_closed
virtual void on_event_closed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2500
zmq::proxy_steerable
void proxy_steerable(void *frontend, void *backend, void *capture, void *control)
Definition: 3rdparty/cppzmq/zmq.hpp:2259
zmq::message_t::rebuild
void rebuild()
Definition: 3rdparty/cppzmq/zmq.hpp:512
lexy::_detail::is_ascii
constexpr bool is_ascii(CharT c)
Definition: encoding.hpp:269
zmq::socket_t::socket_t
socket_t() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2160
zmq::monitor_t
Definition: 3rdparty/cppzmq/zmq.hpp:2278
zmq::monitor_t::on_event_handshake_succeeded
virtual void on_event_handshake_succeeded(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2534
magic_enum::detail::n
constexpr auto n() noexcept
Definition: magic_enum.hpp:417
zmq::detail::socket_base::socket_base
socket_base() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:1704
zmq::message_t::message_t
message_t() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:411
ZMQ_EXPLICIT
#define ZMQ_EXPLICIT
Definition: 3rdparty/cppzmq/zmq.hpp:90
zmq::from_handle_t::_private
Definition: 3rdparty/cppzmq/zmq.hpp:2070
zmq::message_t::rebuild
void rebuild(const void *data_, size_t size_)
Definition: 3rdparty/cppzmq/zmq.hpp:531
zmq::message_t::message_t
message_t(const void *data_, size_t size_)
Definition: 3rdparty/cppzmq/zmq.hpp:437
zmq::free_fn
zmq_free_fn free_fn
Definition: 3rdparty/cppzmq/zmq.hpp:275
ZMQ_CONSTEXPR_FN
#define ZMQ_CONSTEXPR_FN
Definition: 3rdparty/cppzmq/zmq.hpp:93
detail::get
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.hpp:5342
zmq::monitor_t::on_event_connect_retried
virtual void on_event_connect_retried(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2474
cx::begin
constexpr auto begin(const C &c) -> decltype(c.begin())
Definition: wildcards.hpp:661
magic_enum::bitwise_operators::operator~
constexpr E operator~(E rhs) noexcept
Definition: magic_enum.hpp:1422
zmq::monitor_t::init
void init(socket_t &socket, const char *addr_, int events=ZMQ_EVENT_ALL)
Definition: 3rdparty/cppzmq/zmq.hpp:2322
zmq::detail::socket_base::getsockopt
void getsockopt(int option_, void *optval_, size_t *optvallen_) const
Definition: 3rdparty/cppzmq/zmq.hpp:1723
zmq::detail::socket_base::connect
void connect(const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:1870
zmq::socket_t::socket_t
socket_t(context_t &context_, int type_)
Definition: 3rdparty/cppzmq/zmq.hpp:2162
detail::hash
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition: json.hpp:6022
zmq::detail::socket_base::flags_
T int flags_
Definition: 3rdparty/cppzmq/zmq.hpp:1916
zmq::detail::socket_base
Definition: 3rdparty/cppzmq/zmq.hpp:1701
zmq::operator!=
bool operator!=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2117
std
Definition: std.hpp:30
zmq::detail::socket_base::get_option
void get_option(int option_, void *optval_, size_t *optvallen_) const
Definition: 3rdparty/cppzmq/zmq.hpp:2059
lexyd::ascii::control
constexpr auto control
Definition: ascii.hpp:42
zmq::monitor_t::on_event_connected
virtual void on_event_connected(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2463
zmq::detail::socket_base::disconnect
void disconnect(std::string const &addr)
Definition: 3rdparty/cppzmq/zmq.hpp:1877
zmq::detail::socket_base::connect
void connect(std::string const &addr)
Definition: 3rdparty/cppzmq/zmq.hpp:1868
lexyd::byte
constexpr auto byte
Matches an arbitrary byte.
Definition: byte.hpp:51
zmq::message_t::data
T * data() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:602
zmq::detail::socket_base::bind
void bind(std::string const &addr)
Definition: 3rdparty/cppzmq/zmq.hpp:1850
zmq::message_t::copy
void copy(message_t &msg_)
Definition: 3rdparty/cppzmq/zmq.hpp:575
ZMQ_NULLPTR
#define ZMQ_NULLPTR
Definition: 3rdparty/cppzmq/zmq.hpp:92
zmq::message_t::rebuild
void rebuild(size_t size_)
Definition: 3rdparty/cppzmq/zmq.hpp:521
zmq::message_t::str
std::string str() const
Definition: 3rdparty/cppzmq/zmq.hpp:688
detail::value_t
value_t
the JSON type enumeration
Definition: json.hpp:2872
zmq::socket_t::~socket_t
~socket_t() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2193
zmq::message_t::empty
ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:600
zmq::message_t::operator==
bool operator==(const message_t &other) const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:612
zmq::error_t::error_t
error_t(int err) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:293
zmq::message_t::operator=
void operator=(const message_t &) ZMQ_DELETED_FUNCTION
zmq::socket_ref::socket_ref
socket_ref() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2084
zmq::monitor_t::close
void close() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2567
lexyd::operator+
constexpr auto operator+(Rule rule, _br< Condition, R... >)
Definition: branch.hpp:72
zmq::monitor_t::on_event_accepted
virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2490
std::swap
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.hpp:24537
zmq::context_t::~context_t
~context_t() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:827
zmq::context_t::context_t
context_t(int io_threads_, int max_sockets_=ZMQ_MAX_SOCKETS_DFLT)
Definition: 3rdparty/cppzmq/zmq.hpp:804
zmq::monitor_t::on_event_connect_delayed
virtual void on_event_connect_delayed(const zmq_event_t &event_, const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:2468
zmq::detail::socket_base::unbind
void unbind(const char *addr_)
Definition: 3rdparty/cppzmq/zmq.hpp:1861
zmq::message_t::msg
zmq_msg_t msg
Definition: 3rdparty/cppzmq/zmq.hpp:735
zmq_event_t::value
int32_t value
Definition: 3rdparty/cppzmq/zmq.hpp:210
ZMQ_CPP11_DEPRECATED
#define ZMQ_CPP11_DEPRECATED(msg)
Definition: 3rdparty/cppzmq/zmq.hpp:95
lexy::_detail::declval
std::add_rvalue_reference_t< T > declval()
zmq::message_t::move
void move(message_t const *msg_)
Definition: 3rdparty/cppzmq/zmq.hpp:553
zmq::message_t::size
size_t size() const ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:595
zmq::error_t::what
virtual const char * what() const ZMQ_NOTHROW ZMQ_OVERRIDE
Definition: 3rdparty/cppzmq/zmq.hpp:294
lexyd::capture
constexpr auto capture(Token)
Captures whatever the token matches as a lexeme; does not include trailing whitespace.
Definition: capture.hpp:127
zmq::context_t::getctxopt
int getctxopt(int option_)
Definition: 3rdparty/cppzmq/zmq.hpp:838
zmq::message_t::~message_t
~message_t() ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:506
lexyd::p
constexpr auto p
Parses the production.
Definition: production.hpp:127
zmq::message_t::rebuild
void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_=ZMQ_NULLPTR)
Definition: 3rdparty/cppzmq/zmq.hpp:542
zmq::error_t
Definition: 3rdparty/cppzmq/zmq.hpp:289
lexy::_detail::string_view
basic_string_view< char > string_view
Definition: string_view.hpp:184
zmq::message_t::message_t
message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_=ZMQ_NULLPTR)
Definition: 3rdparty/cppzmq/zmq.hpp:449
zmq::monitor_t::operator=
void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION
zmq::operator<=
bool operator<=(const detail::socket_base &a, const detail::socket_base &b) ZMQ_NOTHROW
Definition: 3rdparty/cppzmq/zmq.hpp:2129
lexyd::operator&
constexpr auto operator&(C1 c1, C2 c2) -> _cand< decltype(_make_char_class(c1)), decltype(_make_char_class(c2))>
Definition: char_class.hpp:584
zmq::monitor_t::_monitor_socket
socket_t _monitor_socket
Definition: 3rdparty/cppzmq/zmq.hpp:2565


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:08