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; }
int nn_efd_wait (struct nn_efd *self, int timeout) { int rc; struct pollfd pfd; uint64_t expire; if (timeout > 0) { expire = nn_clock_ms() + timeout; } else { expire = timeout; } /* In order to solve a problem where the poll call doesn't wake up when a file is closed, we sleep a maximum of 100 msec. This is a somewhat unfortunate band-aid to prevent hangs caused by a race condition involving nn_close. In the future this code should be replaced by a simpler design using condition variables. */ for (;;) { pfd.fd = nn_efd_getfd (self); pfd.events = POLLIN; if (nn_slow (pfd.fd < 0)) return -EBADF; switch (expire) { case 0: /* poll once */ timeout = 0; break; case (uint64_t)-1: /* infinite wait */ timeout = 100; break; default: /* bounded wait */ timeout = (int)(expire - nn_clock_ms()); if (timeout < 0) { return -ETIMEDOUT; } if (timeout > 100) { timeout = 100; } } rc = poll (&pfd, 1, timeout); if (nn_slow (rc < 0 && errno == EINTR)) return -EINTR; errno_assert (rc >= 0); if (nn_slow (rc == 0)) { if (expire == 0) return -ETIMEDOUT; if ((expire != (uint64_t)-1) && (expire < nn_clock_ms())) { return -ETIMEDOUT; } continue; } return 0; } }
int nn_efd_wait (struct nn_efd *self, int timeout) { int rc; struct pollfd pfd; pfd.fd = nn_efd_getfd (self); pfd.events = POLLIN; rc = poll (&pfd, 1, timeout); if (nn_slow (rc < 0 && errno == EINTR)) return -EINTR; errno_assert (rc >= 0); if (nn_slow (rc == 0)) return -ETIMEDOUT; return 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; }
int nn_sock_getopt_inner (struct nn_sock *self, int level, int option, void *optval, size_t *optvallen) { int rc; struct nn_optset *optset; int intval; nn_fd fd; /* Generic socket-level options. */ if (level == NN_SOL_SOCKET) { switch (option) { case NN_DOMAIN: intval = self->socktype->domain; break; case NN_PROTOCOL: intval = self->socktype->protocol; break; case NN_LINGER: intval = self->linger; break; case NN_SNDBUF: intval = self->sndbuf; break; case NN_RCVBUF: intval = self->rcvbuf; break; case NN_RCVMAXSIZE: intval = self->rcvmaxsize; break; case NN_SNDTIMEO: intval = self->sndtimeo; break; case NN_RCVTIMEO: intval = self->rcvtimeo; break; case NN_RECONNECT_IVL: intval = self->reconnect_ivl; break; case NN_RECONNECT_IVL_MAX: intval = self->reconnect_ivl_max; break; case NN_SNDPRIO: intval = self->ep_template.sndprio; break; case NN_RCVPRIO: intval = self->ep_template.rcvprio; break; case NN_IPV4ONLY: intval = self->ep_template.ipv4only; break; case NN_SNDFD: if (self->socktype->flags & NN_SOCKTYPE_FLAG_NOSEND) return -ENOPROTOOPT; fd = nn_efd_getfd (&self->sndfd); memcpy (optval, &fd, *optvallen < sizeof (nn_fd) ? *optvallen : sizeof (nn_fd)); *optvallen = sizeof (nn_fd); return 0; case NN_RCVFD: if (self->socktype->flags & NN_SOCKTYPE_FLAG_NORECV) return -ENOPROTOOPT; fd = nn_efd_getfd (&self->rcvfd); memcpy (optval, &fd, *optvallen < sizeof (nn_fd) ? *optvallen : sizeof (nn_fd)); *optvallen = sizeof (nn_fd); return 0; case NN_SOCKET_NAME: strncpy (optval, self->socket_name, *optvallen); *optvallen = strlen(self->socket_name); return 0; default: return -ENOPROTOOPT; } memcpy (optval, &intval, *optvallen < sizeof (int) ? *optvallen : sizeof (int)); *optvallen = sizeof (int); return 0; } /* Protocol-specific socket options. */ if (level > NN_SOL_SOCKET) return rc = self->sockbase->vfptr->getopt (self->sockbase, level, option, optval, optvallen); /* Transport-specific options. */ if (level < NN_SOL_SOCKET) { optset = nn_sock_optset (self, level); if (!optset) return -ENOPROTOOPT; return optset->vfptr->getopt (optset, option, optval, optvallen); } nn_assert (0); }