예제 #1
0
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();
}
예제 #2
0
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();
	}
}
예제 #3
0
// 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);
}
예제 #4
0
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;
}
예제 #5
0
파일: poller.cpp 프로젝트: hellais/libight
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
}
예제 #6
0
파일: poller.cpp 프로젝트: hellais/libight
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;
}
예제 #7
0
파일: poller.cpp 프로젝트: hellais/libight
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;
}
예제 #8
0
파일: SockSpring.cpp 프로젝트: mjssw/lne
void SockSpring::Shutdown(void)
{
    RefLock();
    if(!shutdown_already_)
        __Shutdown();
    RefUnlock();
    poller()->UnBind(this);
}
예제 #9
0
파일: SockSpring.cpp 프로젝트: mjssw/lne
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();
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
0
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);
}
예제 #14
0
/// 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;
}
예제 #15
0
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;
}
예제 #16
0
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();
}
예제 #17
0
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);
}
예제 #18
0
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);
}
예제 #19
0
파일: poller.cpp 프로젝트: hellais/libight
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;
}
예제 #20
0
파일: poller.cpp 프로젝트: hellais/libight
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;
}
예제 #21
0
void test_create ()
{
    zmq::thread_ctx_t thread_ctx;
    zmq::poller_t poller (thread_ctx);
}