bool SockSpray::HandleBind(SockPoller *binder) { bool result = false; #if defined(LNE_WIN32) DWORD bytes; unsigned long value = 1; GUID guid = WSAID_DISCONNECTEX; if(WSAIoctl(skpad_.socket(), SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &iocp_data_.disconnectex, sizeof(iocp_data_.disconnectex), &bytes, NULL, NULL) == 0 && ioctlsocket(skpad_.socket(), FIONBIO, &value) == 0) { #else int flags = fcntl(skpad_.socket(), F_GETFL); if(flags >= 0 && fcntl(skpad_.socket(), F_SETFL, flags | O_NONBLOCK) == 0) { #endif set_poller(binder); #if defined(LNE_WIN32) if(CreateIoCompletionPort(reinterpret_cast<HANDLE>(skpad_.socket()), poller()->Handle(), static_cast<ULONG_PTR>(skpad_.socket()), 0) != NULL) { iocp_lock_.Lock(); DWORD bytes, flags = 0; int rc = WSARecv(skpad_.socket(), &iocp_data_.buffer, 1, &bytes, &flags, &iocp_data_.overlap[IOCP_READ], NULL); if(rc != SOCKET_ERROR || WSAGetLastError() == ERROR_IO_PENDING) { ++iocp_data_.count; result = true; } iocp_lock_.Unlock(); } #elif defined(LNE_LINUX) if(epoll_ctl(poller()->Handle(), EPOLL_CTL_ADD, skpad_.socket(), &epoll_data_) == 0) result = true; #elif defined(LNE_FREEBSD) struct kevent kev[2]; EV_SET(&kev[0], skpad_.socket(), EVFILT_READ, EV_ADD | EV_DISABLE | EV_CLEAR, 0, 0, static_cast<SockEventer *>(this)); EV_SET(&kev[1], skpad_.socket(), EVFILT_WRITE, EV_ADD | EV_DISABLE | EV_CLEAR, 0, 0, static_cast<SockEventer *>(this)); if(kevent(poller()->Handle(), kev, 2, NULL, 0, NULL) == 0) { kevent_data_.num_eof = 1; EV_SET(&kev[0], skpad_.socket(), EVFILT_READ, EV_ENABLE, 0, 0, static_cast<SockEventer *>(this)); EV_SET(&kev[1], skpad_.socket(), EVFILT_WRITE, EV_ENABLE, 0, 0, static_cast<SockEventer *>(this)); kevent(poller()->Handle(), kev, 2, NULL, 0, NULL); result = true; } #endif } if(!result) Clean(); return result; } void SockSpray::HandleTerminate(void) { __Shutdown(); handler_->HandleTerminate(this); Release(); }
void SockSpray::LeaveThreadSafe(void) { LNE_UINT num_flag = 0; thread_lock_.Lock(); --thread_count_; if(thread_count_ == 0) ++num_flag; thread_lock_.Unlock(); shutdown_lock_.Lock(); if(shutdown_state_.already) ++num_flag; shutdown_lock_.Unlock(); #if defined(LNE_WIN32) if(num_flag > 0) { iocp_lock_.Lock(); if(iocp_data_.count > 0) num_flag = 0; iocp_lock_.Unlock(); } #endif // process shutdown if(num_flag == 2) { poller()->UnBind(this); handler_->HandleShutdown(this); Release(); } }
// TODO this triggers an assertion. should it be a valid use case? void test_start_empty () { zmq::thread_ctx_t thread_ctx; zmq::poller_t poller (thread_ctx); poller.start (); msleep (SETTLE_TIME); }
int main() { czmqpp::context ctx; assert(ctx.self()); // Create a few sockets czmqpp::socket vent(ctx, ZMQ_PUSH); int rc = vent.bind("tcp://*:9000"); assert(rc != -1); czmqpp::socket sink(ctx, ZMQ_PULL); rc = sink.connect("tcp://localhost:9000"); assert(rc != -1); czmqpp::socket bowl(ctx, ZMQ_PULL); czmqpp::socket dish(ctx, ZMQ_PULL); // Set-up poller czmqpp::poller poller(bowl, sink, dish); assert(poller.self()); zstr_send(vent.self(), "Hello, World"); // We expect a message only on the sink czmqpp::socket which = poller.wait(-1); assert(which == sink); assert(poller.expired() == false); assert(poller.terminated() == false); char *message = zstr_recv(which.self()); assert(streq(message, "Hello, World")); free(message); return 0; }
static void test_event_del_failure(void) { #ifndef WIN32 auto libevent = IghtLibevent(); std::cout << "Test event_del_failure... "; libevent.event_del = [](event *) { return (-1); }; IghtPoller poller(&libevent); poller.break_loop_on_sigint_(true); auto runtime_error_fired = false; try { poller.break_loop_on_sigint_(false); } catch (std::runtime_error&) { runtime_error_fired = true; } if (runtime_error_fired) std::cout << "ok"; else std::cout << "FAIL"; std::cout << std::endl; #endif }
static void test_break_loop(void) { IghtLibevent libevent; std::cout << "Test break_loop... "; libevent.event_base_loopbreak = [](event_base *) { return (-1); }; IghtPoller poller(&libevent); auto runtime_error_fired = false; try { poller.break_loop(); } catch (std::runtime_error&) { runtime_error_fired = true; } if (runtime_error_fired) std::cout << "ok"; else std::cout << "FAIL"; std::cout << std::endl; }
static void test_evdns_base_new_failure(void) { auto libevent = IghtLibevent(); std::cout << "Test evdns_base_new_failure... "; auto event_base_free_fired = false; libevent.event_base_free = [&event_base_free_fired](event_base *b) { event_base_free_fired = true; ::event_base_free(b); }; libevent.evdns_base_new = [](event_base *, int) { return ((evdns_base *) NULL); }; auto bad_alloc_fired = false; try { IghtPoller poller(&libevent); } catch (std::bad_alloc&) { bad_alloc_fired = true; } if (bad_alloc_fired && event_base_free_fired) std::cout << "ok"; else std::cout << "FAIL"; std::cout << std::endl; }
void SockSpring::Shutdown(void) { RefLock(); if(!shutdown_already_) __Shutdown(); RefUnlock(); poller()->UnBind(this); }
bool SockSpring::HandleBind(SockPoller *binder) { bool result = false; #if defined(LNE_WIN32) iocp_data_.child = socket(skpad_.family(), SOCK_STREAM, IPPROTO_TCP); if(iocp_data_.child != INVALID_SOCKET) { #else int flags = fcntl(skpad_.socket(), F_GETFL); if(flags >= 0 && fcntl(skpad_.socket(), F_SETFL, flags | O_NONBLOCK) == 0) { #endif set_poller(binder); #if defined(LNE_WIN32) if(CreateIoCompletionPort(reinterpret_cast<HANDLE>(skpad_.socket()), poller()->Handle(), static_cast<ULONG_PTR>(skpad_.socket()), 0) != NULL) { DWORD bytes; if(AcceptEx(skpad_.socket(), iocp_data_.child, iocp_data_.address, 0, 0, sizeof(iocp_data_.address), &bytes, &iocp_data_) || WSAGetLastError() == ERROR_IO_PENDING) result = true; } #elif defined(LNE_LINUX) if(epoll_ctl(poller()->Handle(), EPOLL_CTL_ADD, skpad_.socket(), &epoll_data_) == 0) result = true; #elif defined(LNE_FREEBSD) struct kevent kev[1]; EV_SET(&kev[0], skpad_.socket(), EVFILT_READ, EV_ADD, 0, 0, static_cast<SockEventer *>(this)); if(kevent(poller()->Handle(), kev, 1, NULL, 0, NULL) == 0) result = true; #endif } if(!result) Clean(); return result; } void SockSpring::HandleRead(void) { AddRef(); __HandleRead(); Release(); }
bool Notices::modify_notice_internal(NoticeId id, Notice const& notice) { if (Notice* notice_ptr = find_notice(id)) { epoll_event ev; ev.events = translate_event_types(notice); if (::epoll_ctl(poller().raw_handle(), EPOLL_CTL_MOD, notice_ptr->raw_handle(), &ev) == 0) { notice_ptr->set_event_handler(notice.event_handler()); notice_ptr->set_event_types(notice.event_types()); return true; } on_error_ && on_error_(util::errc()); } return false; }
bool Notices::remove_notice_internal(NoticeId id) { if (Notice* notice_ptr = find_notice(id)) { int raw_handle = notice_ptr->raw_handle(); if (notices_.erase(id)) { int ret = ::epoll_ctl(poller().raw_handle(), EPOLL_CTL_DEL, raw_handle, nullptr); // If owner closes the file descriptor, epoll_ctl returns EBADF, which can be ignored if (ret == 0 || errno == EBADF) return true; on_error_ && on_error_(util::errc()); } } return false; }
bool Notices::add_notice_internal(Notice&& notice) { assert(notice.any_event_type()); auto res = notices_.insert(std::make_pair(notice.id(), std::move(notice))); if (res.second) { Notice *notice_ptr = &(res.first->second); epoll_event ev; ev.data.ptr = notice_ptr; ev.events = translate_event_types(*notice_ptr); if (::epoll_ctl(poller().raw_handle(), EPOLL_CTL_ADD, notice_ptr->raw_handle(), &ev) == 0) return true; notices_.erase(res.first); on_error_ && on_error_(util::errc()); } return false; }
void test_add_fd_with_pending_failing_connect () { zmq::thread_ctx_t thread_ctx; zmq::poller_t poller (thread_ctx); zmq::fd_t bind_socket = socket (AF_INET, SOCK_STREAM, 0); sockaddr_in addr = {0}; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); addr.sin_port = 0; TEST_ASSERT_EQUAL_INT (0, bind (bind_socket, reinterpret_cast<const sockaddr *> (&addr), sizeof (addr))); int addr_len = static_cast<int> (sizeof (addr)); TEST_ASSERT_EQUAL_INT (0, getsockname (bind_socket, reinterpret_cast<sockaddr *> (&addr), &addr_len)); zmq::fd_t connect_socket = socket (AF_INET, SOCK_STREAM, 0); zmq::unblock_socket (connect_socket); TEST_ASSERT_EQUAL_INT ( -1, connect (connect_socket, reinterpret_cast<const sockaddr *> (&addr), sizeof (addr))); TEST_ASSERT_EQUAL_INT (WSAEWOULDBLOCK, WSAGetLastError ()); test_events_t events (connect_socket, poller); zmq::poller_t::handle_t handle = poller.add_fd (connect_socket, &events); events.set_handle (handle); poller.set_pollin (handle); poller.start (); wait_in_events (events); int value; int value_len = sizeof (value); TEST_ASSERT_EQUAL_INT (0, getsockopt (connect_socket, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *> (&value), &value_len)); TEST_ASSERT_EQUAL_INT (WSAECONNREFUSED, value); // required cleanup close (connect_socket); close (bind_socket); }
/// PollLoop /// // bool PollLoop::loop(std::chrono::milliseconds timeout) { Poller poller(EPOLL_CLOEXEC); notices_.set_poller(&poller); while (!quit_) { notices_.apply_updates(); poller.poll(timeout); for (unsigned i = 0; i < poller.active_count(); ++i) { epoll_event const& ev = poller.raw_event(i); Notice* notice = notices_.find_notice(ev); translate_events(ev, *notice); dispatch(*notice, notices_); } } return true; }
std::string read_line::get_line() { std::string data; czmqpp::message message; czmqpp::poller poller(socket_); czmqpp::socket which = poller.wait(1); if (!poller.expired() && !poller.terminated() && (which == socket_)) { if (message.receive(socket_)) { const auto& first = message.parts().front(); data = std::string(first.begin(), first.end()); } } return data; }
void SockSpray::HandleShutdown(void) { #if defined(LNE_WIN32) iocp_lock_.Lock(); --iocp_data_.count; iocp_lock_.Unlock(); #elif defined(LNE_LINUX) epoll_ctl(poller()->Handle(), EPOLL_CTL_DEL, skpad_.socket(), &epoll_data_); #elif defined(LNE_FREEBSD) bool to_handle = false; kevent_lock_.Lock(); if(--kevent_data_.num_eof == 0) to_handle = true; kevent_lock_.Unlock(); if(!to_handle) return; #endif EnterThreadSafe(); __HandleShutdown(); LeaveThreadSafe(); }
void test_add_fd_and_remove_by_timer () { zmq::fd_t r, w; create_nonblocking_fdpair (&r, &w); zmq::thread_ctx_t thread_ctx; zmq::poller_t poller (thread_ctx); test_events_t events (r, poller); zmq::poller_t::handle_t handle = poller.add_fd (r, &events); events.set_handle (handle); poller.add_timer (50, &events, 0); poller.start (); wait_timer_events (events); // required cleanup close_fdpair (w, r); }
void test_add_fd_and_start_and_receive_data () { zmq::thread_ctx_t thread_ctx; zmq::poller_t poller (thread_ctx); zmq::fd_t r, w; create_nonblocking_fdpair (&r, &w); test_events_t events (r, poller); zmq::poller_t::handle_t handle = poller.add_fd (r, &events); events.set_handle (handle); poller.set_pollin (handle); poller.start (); send_signal (w); wait_in_events (events); // required cleanup close_fdpair (w, r); }
static void test_evsignal_failure(void) { auto libevent = IghtLibevent(); std::cout << "Test evsignal_failure... "; auto event_base_free_fired = false; auto evdns_base_free_fired = false; libevent.event_base_free = [&event_base_free_fired](event_base *b) { event_base_free_fired = true; ::event_base_free(b); }; libevent.evdns_base_free = [&evdns_base_free_fired](evdns_base *b, int opt) { evdns_base_free_fired = true; ::evdns_base_free(b, opt); }; libevent.event_new = [](event_base *, evutil_socket_t, short, event_callback_fn, void *) { return ((event *) NULL); }; auto bad_alloc_fired = false; try { IghtPoller poller(&libevent); } catch (std::bad_alloc&) { bad_alloc_fired = true; } if (bad_alloc_fired && event_base_free_fired && evdns_base_free_fired) std::cout << "ok"; else std::cout << "FAIL"; std::cout << std::endl; }
static void test_proper_destruction(void) { auto libevent = IghtLibevent(); std::cout << "Test proper_destruction... "; auto event_base_free_fired = false; auto evdns_base_free_fired = false; auto event_free_fired = false; libevent.event_base_free = [&event_base_free_fired](event_base *b) { event_base_free_fired = true; ::event_base_free(b); }; libevent.evdns_base_free = [&evdns_base_free_fired](evdns_base *b, int opt) { evdns_base_free_fired = true; ::evdns_base_free(b, opt); }; libevent.event_free = [&event_free_fired](event *e) { event_free_fired = true; ::event_free(e); }; { IghtPoller poller(&libevent); } if (event_base_free_fired && evdns_base_free_fired && event_free_fired) std::cout << "ok"; else std::cout << "FAIL"; std::cout << std::endl; }
void test_create () { zmq::thread_ctx_t thread_ctx; zmq::poller_t poller (thread_ctx); }