| | |
| | | #include <unordered_map> |
| | | #include <mutex> |
| | | #include <condition_variable> |
| | | #include <tuple> |
| | | #include <unistd.h> |
| | | |
| | | #include "nng/compat/nanomsg/nn.h" |
| | | #include <nng/nng.h> |
| | | |
| | | namespace nng_wrap { |
| | | template <class... T> struct make_void{typedef void type;}; |
| | | template <class... T> using void_t = typename make_void<T...>::type; |
| | | template <class T, typename = void> struct is_default_c : std::false_type{}; |
| | | template <class T> struct is_default_c<T, void_t<decltype(T())>> : std::true_type{}; |
| | | template<class T> using is_function_t = typename std::is_function<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type; |
| | | template <bool, class T> struct is_callable_h : is_function_t<T>{}; |
| | | template <class T> struct is_callable_h<true, T>{ |
| | | private: |
| | | struct FB{void operator()();}; |
| | | struct D : T, FB{}; |
| | | template<typename U, U> struct c; |
| | | template<class> static std::true_type t(...); |
| | | template<class C> static std::false_type t(c<void(FB::*)(), &C::operator()>*); |
| | | public: |
| | | using type = decltype(t<D>(nullptr)); |
| | | }; |
| | | template <class T> using is_callable = typename is_callable_h<std::is_class<typename std::remove_reference<T>::type>::value, typename std::remove_reference<T>::type>::type; |
| | | |
| | | static thread_local std::string verbose_info{}; |
| | | #ifndef PRNTVITAG |
| | |
| | | public: |
| | | struct psmsg{ |
| | | DISABLE_COPY_AND_ASSIGN(psmsg); |
| | | psmsg()=delete; |
| | | psmsg(const std::string& t, std::string&& m) |
| | | :topic_(t),data_(std::move(m)){} |
| | | std::string topic_{}; |
| | |
| | | DISABLE_COPY_AND_ASSIGN(_rr); |
| | | _rr()=default; |
| | | ~_rr(){ |
| | | if(sock_local_.id > 0) nng_close(sock_local_); |
| | | if(sock_remote_.id > 0) nng_close(sock_remote_); |
| | | if(std::get<0>(socks_).id > 0) nng_close(std::get<0>(socks_)); |
| | | if(std::get<0>(std::get<1>(socks_)).id > 0) nng_close(std::get<0>(std::get<1>(socks_))); |
| | | t_quit_.store(true, std::memory_order_relaxed); |
| | | if (t_unblock_&&t_unblock_->joinable()) t_unblock_->join(); |
| | | } |
| | | |
| | | |
| | | std::unique_ptr<std::thread> t_unblock_{nullptr}; |
| | | std::atomic_bool t_quit_{false}; |
| | | |
| | | nng_socket sock_local_{0}; |
| | | nng_socket sock_remote_{0}; |
| | | int port_{-1}; |
| | | std::tuple<nng_socket, std::tuple<nng_socket, int>> socks_; |
| | | |
| | | std::unordered_map<uint64_t, std::string> msg_{}; |
| | | class worker{ |
| | | worker& in_op(const worker& w){if(&w!=this){w_=w.w_;life_=w.life_;}return *this;}; |
| | | public: |
| | | worker()=default; |
| | | ~worker()=default; |
| | | worker(struct work* w):w_(w),life_(0){} |
| | | worker(const worker& w):w_(w.w_),life_(w.life_){} |
| | | worker(worker&& w):w_(w.w_),life_(w.life_){} |
| | | worker& operator=(const worker& w){return in_op(w);} |
| | | worker& operator=(worker&& w){return in_op(w);} |
| | | operator struct work*() const{return w_;} |
| | | operator int&() {return life_;} |
| | | struct work* w_{}; |
| | |
| | | |
| | | }; |
| | | |
| | | template<class T> inline T* singleton(){ static T t; return &t; } |
| | | template<class T, typename std::enable_if<is_default_c<T>::value, int>::type=0> inline T* singleton(){ static auto t = std::make_unique<T>(); return t.get(); } |
| | | |
| | | template <class T, class... Args, typename std::enable_if<is_callable<T>::value, int>::type=0> |
| | | inline std::thread get_thread(T&& t, Args&&... args){ |
| | | return std::thread(std::forward<T>(t), std::forward<Args>(args)...); |
| | | } |
| | | |
| | | } |
| | | #endif |