Esempio n. 1
0
int main()
{
    int i;
    struct nn_thread srv_thread;
    struct nn_thread cli_threads[THREAD_COUNT];
    /*  Stress the shutdown algorithm. */
    nn_thread_init(&srv_thread, server, NULL);

    for (i = 0; i != THREAD_COUNT; ++i)
        nn_thread_init(&cli_threads[i], client, (void *)(intptr_t)i);
    for (i = 0; i != THREAD_COUNT; ++i)
        nn_thread_term(&cli_threads[i]);

    return 0;
}
Esempio n. 2
0
int main ()
{
    int rc;
    int sb;
    int i;
    int j;
    struct nn_thread threads [THREAD_COUNT];

    /*  Stress the shutdown algorithm. */

    sb = nn_socket (AF_SP, NN_PUB);
    errno_assert (sb >= 0);
    rc = nn_bind (sb, SOCKET_ADDRESS);
    errno_assert (rc >= 0);

    for (j = 0; j != 10; ++j) {
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_init (&threads [i], routine, NULL);
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_term (&threads [i]);
    }

    rc = nn_close (sb);
    errno_assert (rc == 0);

    return 0;
}
Esempio n. 3
0
int main ()
{
#if !defined NN_HAVE_WINDOWS
    int sb;
    int i;
    int j;
    struct nn_thread threads [THREAD_COUNT];

    /*  Stress the shutdown algorithm. */

    sb = test_socket (AF_SP, NN_PUB);
    test_bind (sb, SOCKET_ADDRESS);

    for (j = 0; j != 10; ++j) {
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_init (&threads [i], routine, NULL);
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_term (&threads [i]);
    }

    test_close (sb);

#endif

    return 0;
}
Esempio n. 4
0
int testterm()
{
    int rc;
    int s;
    struct nn_thread thread;
    printf("test term\n");

    /*  Close the socket with no associated endpoints. */
    s = test_socket (AF_SP, NN_PAIR);
    test_close (s);

    /*  Test nn_term() before nn_close(). */
    nn_thread_init (&thread, worker, NULL);
    nn_sleep (100);
    nn_term();

    /*  Check that it's not possible to create new sockets after nn_term(). */
    rc = nn_socket (AF_SP, NN_PAIR);
    nn_assert (rc == -1);
    errno_assert (nn_errno () == ETERM);

    /*  Wait till worker thread terminates. */
    nn_thread_term(&thread);
    printf("nn_thread_term finished\n");
    return 0;
}
Esempio n. 5
0
int nn_worker_init(struct nn_worker *self)
{
    int32_t rc;
    //PostMessage("nn_worker_init %p\n",self);
    rc = nn_efd_init(&self->efd);
    //PostMessage("efd init: rc.%d\n",rc);
    if ( rc < 0 )
        return rc;
    //PostMessage("nn_mutex_init\n");
    nn_mutex_init(&self->sync);
    //PostMessage("nn_queue_init\n");
    nn_queue_init(&self->tasks);
    //PostMessage("nn_queue_item_init\n");
    nn_queue_item_init(&self->stop);
    //PostMessage("nn_poller_init\n");
    nn_poller_init(&self->poller);
    //PostMessage("nn_poller_add\n");
    nn_poller_add(&self->poller,nn_efd_getfd(&self->efd),&self->efd_hndl);
    //PostMessage("nn_poller_set_in\n");
    nn_poller_set_in(&self->poller, &self->efd_hndl);
    //PostMessage("nn_timerset_init\n");
    nn_timerset_init(&self->timerset);
    //PostMessage("nn_thread_init\n");
    nn_thread_init(&self->thread,nn_worker_routine, self);
    //PostMessage("finished nn_worker_init\n");
    return 0;
}
Esempio n. 6
0
int main ()
{
    int rc;
    char buf [3];
    struct nn_thread thread;

    sb = nn_socket (AF_SP, NN_PAIR);
    errno_assert (sb != -1);
    rc = nn_bind (sb, SOCKET_ADDRESS);
    errno_assert (rc >= 0);
    sc = nn_socket (AF_SP, NN_PAIR);
    errno_assert (sc != -1);
    rc = nn_connect (sc, SOCKET_ADDRESS);
    errno_assert (rc >= 0);

    nn_thread_init (&thread, worker, NULL);

    rc = nn_recv (sb, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);
    rc = nn_recv (sb, buf, sizeof (buf), 0);
    errno_assert (rc >= 0);
    nn_assert (rc == 3);

    nn_thread_term (&thread);

    rc = nn_close (sc);
    errno_assert (rc == 0);
    rc = nn_close (sb);
    errno_assert (rc == 0);

    return 0;
}
Esempio n. 7
0
int main (int argc, const char *argv[])
{
    int end0;
    int end1;
    struct nn_thread thread5;
    struct nn_thread thread6;

    int port = get_test_port(argc, argv);

    test_addr_from(socket_address_h, "tcp", "127.0.0.1", port);
    test_addr_from(socket_address_i, "tcp", "127.0.0.1", port + 1);
    test_addr_from(socket_address_j, "tcp", "127.0.0.1", port + 2);

    /*  Test the bi-directional device with REQ/REP (headers). */

    /*  Start the devices. */
    nn_thread_init (&thread5, device5, NULL);
    nn_thread_init (&thread6, device6, NULL);

    /*  Create two sockets to connect to the device. */
    end0 = test_socket (AF_SP, NN_REQ);
    test_connect (end0, socket_address_h);
    end1 = test_socket (AF_SP, NN_REP);
    test_connect (end1, socket_address_j);

    /*  Wait for TCP to establish. */
    nn_sleep (100);

    /*  Pass a message between endpoints. */
    test_send (end0, "XYZ");
    test_recv (end1, "XYZ");

    /*  Now send a reply. */
    test_send (end1, "REPLYXYZ");
    test_recv (end0, "REPLYXYZ");

    /*  Clean up. */
    test_close (end0);
    test_close (end1);

    /*  Shut down the devices. */
    nn_term ();
    nn_thread_term (&thread5);
    nn_thread_term (&thread6);

    return 0;
}
Esempio n. 8
0
int testipc_shutdown()
{
    int sb;
    int i;
    int j;
    struct nn_thread threads [THREAD_COUNT];
    printf("test ipc shutdown\n");

    /*  Stress the shutdown algorithm. */

#if defined(SIGPIPE) && defined(SIG_IGN)
	signal (SIGPIPE, SIG_IGN);
#endif

    sb = test_socket (AF_SP, NN_PUB);
    test_bind (sb, SOCKET_ADDRESS);

    for (j = 0; j != TEST_LOOPS; ++j) {
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_init (&threads [i], routine, NULL);
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_term (&threads [i]);
    }

    test_close (sb);

    /*  Test race condition of sending message while socket shutting down  */

    sb = test_socket (AF_SP, NN_PUSH);
    test_bind (sb, SOCKET_ADDRESS);

    for (j = 0; j != TEST_LOOPS; ++j) {
        for (i = 0; i != TEST2_THREAD_COUNT; ++i)
            nn_thread_init (&threads [i], routine2, NULL);
        active = TEST2_THREAD_COUNT;
        while ( active )
        {
            (void) nn_send (sb, "hello", 5, NN_DONTWAIT);
        }
        for (i = 0; i != TEST2_THREAD_COUNT; ++i)
            nn_thread_term(&threads [i]);
    }

    test_close (sb);

    return 0;
}
Esempio n. 9
0
int ftw_socket_inbox_construct(struct ftw_socket_inbox **inst, LVUserEventRef *msg_to_lv_event,
    struct ftw_socket_inbox **sock, const LStrHandleArray **addresses, int linger, int max_recv_size)
{
    char *addr;
    int rcb;
    int rcs;
    int rco;
    int i;

    /*  Preconditions expected of LabVIEW. */
    ftw_assert(inst && *inst && addresses && *addresses && msg_to_lv_event && sock);

    rcs = nn_socket(AF_SP_RAW, NN_REP);

    /*  Socket creation failure? */
    if (rcs < 0) {
        *sock = NULL;
        return rcs;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_LINGER, &linger, sizeof(linger));
    if (rco < 0) {
        *sock = NULL;
        return rco;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_RCVMAXSIZE, &max_recv_size, sizeof(max_recv_size));
    if (rco < 0) {
        *sock = NULL;
        return rco;
    }

    for (i = 0; i < (*addresses)->dimsize; i++) {
        addr = ftw_support_LStrHandle_to_CStr((*addresses)->element[i]);
        rcb = nn_bind(rcs, addr);
        ftw_free (addr);
        if (rcb < 0) {
            nn_close(rcs);
            *sock = NULL;
            return rcb;
        }
    }

    (*inst)->incoming_msg_notifier_event = *msg_to_lv_event;
    (*inst)->id = rcs;

    /*  Launch thread and wait for it to initialize. */
    nn_sem_init(&(*inst)->deinitialized);
    nn_sem_init(&(*inst)->initialized);
    nn_sem_init(&(*inst)->msg_acknowledged);
    nn_thread_init(&(*inst)->async_recv_thread, ftw_socket_inbox_async_recv_worker, *inst);
    nn_sem_wait(&(*inst)->initialized);

    *sock = *inst;

    return 0;
}
Esempio n. 10
0
void *portable_thread_create(void *funcp,void *argp)
{
    //void nn_thread_term(struct nn_thread *self);
    void nn_thread_init(struct nn_thread *self,portable_thread_func *routine,void *arg);
    struct nn_thread *ptr;
    ptr = (struct nn_thread *)malloc(sizeof(*ptr));
    nn_thread_init(ptr,(portable_thread_func *)funcp,argp);
    return(ptr);
}
Esempio n. 11
0
int main ()
{
    int sb;
    int i;
    int j;
    struct nn_thread threads [THREAD_COUNT];

    /*  Stress the shutdown algorithm. */

    sb = test_socket (AF_SP, NN_PUB);
    test_bind (sb, SOCKET_ADDRESS);

    for (j = 0; j != TEST_LOOPS; ++j) {
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_init (&threads [i], routine, NULL);
        for (i = 0; i != THREAD_COUNT; ++i)
            nn_thread_term (&threads [i]);
    }

    test_close (sb);

    /*  Test race condition of sending message while socket shutting down  */

    sb = test_socket (AF_SP, NN_PUSH);
    test_bind (sb, SOCKET_ADDRESS);

    for (j = 0; j != TEST_LOOPS; ++j) {
        for (i = 0; i != TEST2_THREAD_COUNT; ++i)
            nn_thread_init (&threads [i], routine2, NULL);
        nn_atomic_init(&active, TEST2_THREAD_COUNT);

        while (active.n) {
            (void) nn_send (sb, "hello", 5, NN_DONTWAIT);
        }

        for (i = 0; i != TEST2_THREAD_COUNT; ++i)
            nn_thread_term (&threads [i]);
        nn_atomic_term(&active);
    }

    test_close (sb);

    return 0;
}
Esempio n. 12
0
int main (int argc, char *argv [])
{
    int rc;
    int s;
    int i;
    char *buf;
    struct nn_thread thread;
    struct nn_stopwatch stopwatch;
    uint64_t elapsed;
    double latency;

    if (argc != 3) {
        printf ("usage: inproc_lat <message-size> <roundtrip-count>\n");
        return 1;
    }

    message_size = atoi (argv [1]);
    roundtrip_count = atoi (argv [2]);

    s = nn_socket (AF_SP, NN_PAIR);
    assert (s != -1);
    rc = nn_bind (s, "inproc://inproc_lat");
    assert (rc >= 0);

    buf = malloc (message_size);
    assert (buf);
    memset (buf, 111, message_size);

    /*  Wait a bit till the worker thread blocks in nn_recv(). */
    nn_thread_init (&thread, worker, NULL);
    nn_sleep (100);

    nn_stopwatch_init (&stopwatch);

    for (i = 0; i != roundtrip_count; i++) {
        rc = nn_send (s, buf, message_size, 0);
        assert (rc == (int)message_size);
        rc = nn_recv (s, buf, message_size, 0);
        assert (rc == (int)message_size);
    }

    elapsed = nn_stopwatch_term (&stopwatch);

    latency = (double) elapsed / (roundtrip_count * 2);
    printf ("message size: %d [B]\n", (int) message_size);
    printf ("roundtrip count: %d\n", (int) roundtrip_count);
    printf ("average latency: %.3f [us]\n", (double) latency);

    nn_thread_term (&thread);
    free (buf);
    rc = nn_close (s);
    assert (rc == 0);

    return 0;
}
Esempio n. 13
0
int main ()
{
    int end0;
    int end1;
    struct nn_thread thread5;
    struct nn_thread thread6;

    /*  Test the bi-directional device with REQ/REP (headers). */

    /*  Start the devices. */
    nn_thread_init (&thread5, device5, NULL);
    nn_thread_init (&thread6, device6, NULL);

    /*  Create two sockets to connect to the device. */
    end0 = test_socket (AF_SP, NN_REQ);
    test_connect (end0, SOCKET_ADDRESS_H);
    end1 = test_socket (AF_SP, NN_REP);
    test_connect (end1, SOCKET_ADDRESS_J);

    /*  Wait for TCP to establish. */
    nn_sleep (1000);

    /*  Pass a message between endpoints. */
    test_send (end0, "XYZ");
    test_recv (end1, "XYZ");

    /*  Now send a reply. */
    test_send (end1, "REPLYXYZ");
    test_recv (end0, "REPLYXYZ");

    /*  Clean up. */
    test_close (end0);
    test_close (end1);

    /*  Shut down the devices. */
    nn_term ();
    nn_thread_term (&thread5);
    nn_thread_term (&thread6);

    return 0;
}
Esempio n. 14
0
int nn_tcpmuxd (int port)
{
    int rc;
    int tcp_listener;
    int ipc_listener;
    int opt;
    struct sockaddr_in tcp_addr;
    struct sockaddr_un ipc_addr;
    struct nn_tcpmuxd_ctx *ctx;

    /*  Start listening on the specified TCP port. */
    tcp_listener = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    errno_assert (tcp_listener >= 0);
    opt = 1;
    rc = setsockopt (tcp_listener, SOL_SOCKET, SO_REUSEADDR, &opt,
        sizeof (opt));
    errno_assert (rc == 0);
    memset (&tcp_addr, 0, sizeof (tcp_addr));
    tcp_addr.sin_family = AF_INET;
    tcp_addr.sin_port = htons (port);
    tcp_addr.sin_addr.s_addr = INADDR_ANY;
    rc = bind (tcp_listener, (struct sockaddr*) &tcp_addr, sizeof (tcp_addr));
    errno_assert (rc == 0);
    rc = listen (tcp_listener, 100);
    errno_assert (rc == 0);

    /*  Start listening for incoming IPC connections. */
    ipc_addr.sun_family = AF_UNIX;
    snprintf (ipc_addr.sun_path, sizeof (ipc_addr.sun_path),
        "/tmp/tcpmux-%d.ipc", (int) port);
    unlink (ipc_addr.sun_path);
    ipc_listener = socket (AF_UNIX, SOCK_STREAM, 0);
    errno_assert (ipc_listener >= 0);
    rc = bind (ipc_listener, (struct sockaddr*) &ipc_addr, sizeof (ipc_addr));
    errno_assert (rc == 0);
    rc = listen (ipc_listener, 100);
    errno_assert (rc == 0);

    /*  Allocate a context for the daemon. */
    ctx = nn_alloc (sizeof (struct nn_tcpmuxd_ctx), "tcpmuxd context");
    alloc_assert (ctx);
    ctx->tcp_listener = tcp_listener;
    ctx->ipc_listener = ipc_listener;
    nn_list_init (&ctx->conns);

    /*  Run the daemon in a dedicated thread. */
    nn_thread_init (&ctx->thread, nn_tcpmuxd_routine, ctx);

    return 0;
}
Esempio n. 15
0
int nn_worker_init (struct nn_worker *self)
{
    int rc;

    rc = nn_efd_init (&self->efd);
    if (rc < 0)
        return rc;

    nn_mutex_init (&self->sync);
    nn_queue_init (&self->tasks);
    nn_queue_item_init (&self->stop);
    nn_poller_init (&self->poller);
    nn_poller_add (&self->poller, nn_efd_getfd (&self->efd), &self->efd_hndl);
    nn_poller_set_in (&self->poller, &self->efd_hndl);
    nn_timerset_init (&self->timerset);
    nn_thread_init (&self->thread, nn_worker_routine, self);

    return 0;
}
Esempio n. 16
0
int main ()
{
    struct nn_thread thread;

    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);

    nn_thread_init (&thread, worker, NULL);

    test_recv (sb, "ABC");
    test_recv (sb, "ABC");

    nn_thread_term (&thread);

    test_close (sc);
    test_close (sb);

    return 0;
}
Esempio n. 17
0
File: device.c Progetto: 0xe/nanomsg
int main ()
{
    int enda;
    int endb;
    int endc;
    int endd;
    int ende1;
    int ende2;
    struct nn_thread thread1;
    struct nn_thread thread2;
    struct nn_thread thread3;
    int timeo;

    /*  Test the bi-directional device. */

    /*  Start the device. */
    nn_thread_init (&thread1, device1, NULL);

    /*  Create two sockets to connect to the device. */
    enda = test_socket (AF_SP, NN_PAIR);
    test_connect (enda, SOCKET_ADDRESS_A);
    endb = test_socket (AF_SP, NN_PAIR);
    test_connect (endb, SOCKET_ADDRESS_B);

    /*  Pass a pair of messages between endpoints. */
    test_send (enda, "ABC");
    test_recv (endb, "ABC");
    test_send (endb, "ABC");
    test_recv (enda, "ABC");

    /*  Clean up. */
    test_close (endb);
    test_close (enda);

    /*  Test the uni-directional device. */

    /*  Start the device. */
    nn_thread_init (&thread2, device2, NULL);

    /*  Create two sockets to connect to the device. */
    endc = test_socket (AF_SP, NN_PUSH);
    test_connect (endc, SOCKET_ADDRESS_C);
    endd = test_socket (AF_SP, NN_PULL);
    test_connect (endd, SOCKET_ADDRESS_D);

    /*  Pass a message between endpoints. */
    test_send (endc, "XYZ");
    test_recv (endd, "XYZ");

    /*  Clean up. */
    test_close (endd);
    test_close (endc);

    /*  Test the loopback device. */

    /*  Start the device. */
    nn_thread_init (&thread3, device3, NULL);

    /*  Create two sockets to connect to the device. */
    ende1 = test_socket (AF_SP, NN_BUS);
    test_connect (ende1, SOCKET_ADDRESS_E);
    ende2 = test_socket (AF_SP, NN_BUS);
    test_connect (ende2, SOCKET_ADDRESS_E);

    /*  BUS is unreliable so wait a bit for connections to be established. */
    nn_sleep (100);

    /*  Pass a message to the bus. */
    test_send (ende1, "KLM");
    test_recv (ende2, "KLM");

    /*  Make sure that the message doesn't arrive at the socket it was
        originally sent to. */
    timeo = 100;
    test_setsockopt (ende1, NN_SOL_SOCKET, NN_RCVTIMEO,
       &timeo, sizeof (timeo));
    test_drop (ende1, ETIMEDOUT);

    /*  Clean up. */
    test_close (ende2);
    test_close (ende1);

    /*  Shut down the devices. */
    nn_term ();
    nn_thread_term (&thread1);
    nn_thread_term (&thread2);
    nn_thread_term (&thread3);

    return 0;
}
Esempio n. 18
0
int main (int argc, char *argv [])
{
    int rc;
    int s;
    int i;
    char *buf;
    struct nn_thread thread;
    struct nn_stopwatch stopwatch;
    uint64_t elapsed;
    unsigned long throughput;
    double megabits;

    if (argc != 3) {
        printf ("usage: thread_thr <message-size> <message-count>\n");
        return 1;
    }

    message_size = atoi (argv [1]);
    message_count = atoi (argv [2]);

    s = nn_socket (AF_SP, NN_PAIR);
    assert (s != -1);
    rc = nn_bind (s, "inproc://inproc_thr");
    assert (rc >= 0);

    buf = malloc (message_size);
    assert (buf);

    nn_thread_init (&thread, worker, NULL);

    /*  First message is used to start the stopwatch. */
    rc = nn_recv (s, buf, message_size, 0);
    assert (rc == 0);

    nn_stopwatch_init (&stopwatch);

    for (i = 0; i != message_count; i++) {
        rc = nn_recv (s, buf, message_size, 0);
        assert (rc == message_size);
    }

    elapsed = nn_stopwatch_term (&stopwatch);

    nn_thread_term (&thread);
    free (buf);
    rc = nn_close (s);
    assert (rc == 0);

    if (elapsed == 0)
        elapsed = 1;
    throughput = (unsigned long)
        ((double) message_count / (double) elapsed * 1000000);
    megabits = (double) (throughput * message_size * 8) / 1000000;

    printf ("message size: %d [B]\n", (int) message_size);
    printf ("message count: %d\n", (int) message_count);
    printf ("mean throughput: %d [msg/s]\n", (int) throughput);
    printf ("mean throughput: %.3f [Mb/s]\n", (double) megabits);

    return 0;
}
Esempio n. 19
0
int ftw_subscriber_construct(struct ftw_socket_callsite **callsite, LVUserEventRef *lv_event,
    const char *addr, int linger, int max_recv_size, struct ftw_socket **sock)
{
    struct ftw_socket *inst;
    int rcc;
    int rcs;
    int rco;

    /*  Preconditions expected of LabVIEW. */
    ftw_assert(*callsite && addr);
    nn_mutex_lock(&(*callsite)->sync);

    rcs = nn_socket(AF_SP, NN_SUB);

    /*  Socket creation failure? */
    if (rcs < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rcs;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_LINGER, &linger, sizeof(linger));
    if (rco < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    rco = nn_setsockopt(rcs, NN_SOL_SOCKET, NN_RCVMAXSIZE, &max_recv_size, sizeof(max_recv_size));
    if (rco < 0) {
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    rcc = nn_connect(rcs, addr);

    /*  Endpoint creation failure? */
    if (rcc < 0) {
        nn_close(rcs);
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rcc;
    }

    rco = nn_setsockopt (rcs, NN_SUB, NN_SUB_SUBSCRIBE, "", 0);
    if (rco < 0) {
        nn_close(rcs);
        *sock = NULL;
        nn_mutex_unlock(&(*callsite)->sync);
        return rco;
    }

    inst = ftw_malloc(sizeof(struct ftw_socket));
    ftw_assert(inst);

    inst->incoming_msg_notifier_event = *lv_event;
    inst->id = rcs;
    inst->callsite = *callsite;

    nn_list_item_init(&inst->item);
    nn_list_insert(&(*callsite)->active_sockets, &inst->item,
        nn_list_end(&(*callsite)->active_sockets));

    nn_sem_init(&inst->msg_acknowledged);

    /*  Launch thread and wait for it to initialize. */
    nn_sem_init(&inst->async_recv_ready);
    nn_thread_init(&inst->async_recv_thread, ftw_subscriber_async_recv_thread, inst);
    nn_sem_wait(&inst->async_recv_ready);

    *sock = inst;

    (*callsite)->lifetime_sockets++;
    nn_mutex_unlock(&(*callsite)->sync);

    return 0;
}
Esempio n. 20
0
int main ()
{
    int rc;
    int sb;
    char buf [3];
    struct nn_thread thread;
    struct nn_pollfd pfd [2];

    /* Test nn_poll() function. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);
    test_send (sc, "ABC");
    nn_sleep (100);
    pfd [0].fd = sb;
    pfd [0].events = NN_POLLIN | NN_POLLOUT;
    pfd [1].fd = sc;
    pfd [1].events = NN_POLLIN | NN_POLLOUT;
    rc = nn_poll (pfd, 2, -1);
    errno_assert (rc >= 0);
    nn_assert (rc == 2);
    nn_assert (pfd [0].revents == (NN_POLLIN | NN_POLLOUT));
    nn_assert (pfd [1].revents == NN_POLLOUT);
    test_close (sc);
    test_close (sb);

    /*  Create a simple topology. */
    sb = test_socket (AF_SP, NN_PAIR);
    test_bind (sb, SOCKET_ADDRESS);
    sc = test_socket (AF_SP, NN_PAIR);
    test_connect (sc, SOCKET_ADDRESS);

    /*  Check the initial state of the socket. */
    rc = getevents (sb, NN_IN | NN_OUT, 1000);
    nn_assert (rc == NN_OUT);

    /*  Poll for IN when there's no message available. The call should
        time out. */
    rc = getevents (sb, NN_IN, 10);
    nn_assert (rc == 0);

    /*  Send a message and start polling. This time IN event should be
        signaled. */
    test_send (sc, "ABC");
    rc = getevents (sb, NN_IN, 1000);
    nn_assert (rc == NN_IN);

    /*  Receive the message and make sure that IN is no longer signaled. */
    test_recv (sb, "ABC");
    rc = getevents (sb, NN_IN, 10);
    nn_assert (rc == 0);

    /*  Check signalling from a different thread. */
    nn_thread_init (&thread, routine1, NULL);
    rc = getevents (sb, NN_IN, 1000);
    nn_assert (rc == NN_IN);
    test_recv (sb, "ABC");
    nn_thread_term (&thread);

    /*  Check terminating the library from a different thread. */
    nn_thread_init (&thread, routine2, NULL);
    rc = getevents (sb, NN_IN, 1000);
    nn_assert (rc == NN_IN);
    rc = nn_recv (sb, buf, sizeof (buf), 0);
    nn_assert (rc < 0 && nn_errno () == ETERM);
    nn_thread_term (&thread);

    /*  Clean up. */
    test_close (sc);
    test_close (sb);

    return 0;
}