⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nbio.c

📁 实现非阻塞方式IO(NBIO)的java类
💻 C
📖 第 1 页 / 共 3 页
字号:
    THROW_EXCEPTION(env, "java/io/IOException", strerror(errno));    return;  }#ifdef USE_BTREE  state->tree = btree_newnode();#else  for (i = 0; i < MAX_FDS; i++) {    state->selitems[i] = (jobject)NULL;  }#endif  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.init opened /dev/poll, fd %d\n", state->devpoll_fd));  state->retevents = (struct pollfd *)malloc(max_retevents * sizeof(struct pollfd));  if (state->retevents == NULL) {    THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "Cannot allocate state->retevents");    return;  }  return;}JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_register (JNIEnv * env, jobject this, jobject selitemobj) {  devpoll_impl_state *state;  jclass cls, cls2;  jfieldID fid, fid2, fid_events;  jobject fdobj;  short events, realevents;  struct pollfd pfd;  void *data;  jobject selitem;  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.register called\n"));  // Get state  cls = (*env)->GetObjectClass(env, this);  fid = (*env)->GetFieldID(env, cls, "native_state", "J");  state = (devpoll_impl_state *)((*env)->GetLongField(env, this, fid));  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.register got state, fd %d\n", state->devpoll_fd));  // Get class and field IDs  cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem");  fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;");  fid_events = (*env)->GetFieldID(env, cls, "events", "S");  cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor");  fid2 = (*env)->GetFieldID(env, cls2, "fd", "I");  // Get fd  fdobj = (*env)->GetObjectField(env, selitemobj, fid);  pfd.fd = (*env)->GetIntField(env, fdobj, fid2);  // Get events  events = (*env)->GetShortField(env, selitemobj, fid_events);  realevents = 0;  if (events != 0) {    if (events & SELECTABLE_READ_READY) {      realevents |= (POLLIN | POLLPRI);    }    if (events & SELECTABLE_WRITE_READY) {      realevents |= POLLOUT;    }    pfd.events = realevents;  }  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.register adding (fd=%d,events=0x%x)\n", pfd.fd, pfd.events));  // Register  if (write(state->devpoll_fd, &pfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {    THROW_EXCEPTION(env, "java/io/IOException", strerror(errno));    return;  }#ifdef USE_BTREE  data = btree_search(state->tree, pfd.fd);  if (data == NULL) {    // Insert into B-tree    state->tree = btree_insert(state->tree, pfd.fd, (*env)->NewGlobalRef(env, selitemobj));  }#else  if ((pfd.fd < 0) || (pfd.fd >= MAX_FDS)) {    fprintf(stderr,"Warning: pfd.fd is %d, out of range 0...%d.\n",MAX_FDS);    fprintf(stderr,"  You need to recompile nbio.c with a larger MAX_FDS value.\n");    return;  }  selitem = state->selitems[pfd.fd];  if (selitem == (jobject)NULL) {    state->selitems[pfd.fd] = (*env)->NewGlobalRef(env, selitemobj);  }#endif  return;}JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_deregister (JNIEnv * env, jobject this, jobject selitemobj) {  devpoll_impl_state *state;  jclass cls, cls2;  jfieldID fid, fid2;  jobject fdobj, selitem;  struct pollfd pfd;  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.deregister called\n"));  // Get state  cls = (*env)->GetObjectClass(env, this);  fid = (*env)->GetFieldID(env, cls, "native_state", "J");  state = (devpoll_impl_state *)((*env)->GetLongField(env, this, fid));  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.deregister got state, fd %d\n", state->devpoll_fd));  // Get class and field IDs  cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem");  fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;");  cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor");  fid2 = (*env)->GetFieldID(env, cls2, "fd", "I");  // Get fd  fdobj = (*env)->GetObjectField(env, selitemobj, fid);  pfd.fd = (*env)->GetIntField(env, fdobj, fid2);  pfd.events = POLLREMOVE;  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.deregister removing (fd=%d,events=0x%x)\n", pfd.fd, pfd.events));  // Deeegister  if (write(state->devpoll_fd, &pfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {    THROW_EXCEPTION(env, "java/io/IOException", strerror(errno));    return;  }#ifdef USE_BTREE  // XXX NEED TO DELETE NODE FROM BTREE#else  if ((pfd.fd < 0) || (pfd.fd >= MAX_FDS)) {    fprintf(stderr,"Warning: pfd.fd is %d, out of range 0...%d.\n",MAX_FDS);    fprintf(stderr,"  You need to recompile nbio.c with a larger MAX_FDS value.\n");    return;  }  selitem = state->selitems[pfd.fd];  if (selitem != (jobject)NULL) {    // selitem can be NULL if deregister is not synchronized     // (although it should be)    (*env)->DeleteGlobalRef(env, selitem);    state->selitems[pfd.fd] = (jobject)NULL;  }#endif  return;}JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_doSelect (JNIEnv * env, jobject this, jint timeout) {  devpoll_impl_state *state;  jclass cls, cls2;  jfieldID fid, fid2, fid_fd, fid_revents;  jobject selitemobj, fdobj;  jobjectArray itemarr, retitemarr;  struct dvpoll dopoll;  int itemarrlen, ret, i, j, fd, retfd, count;  void *data;  struct pollfd *pfd;  short realevents;  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect called\n"));  // Get state  cls = (*env)->GetObjectClass(env, this);  fid = (*env)->GetFieldID(env, cls, "native_state", "J");  state = (devpoll_impl_state *)((*env)->GetLongField(env, this, fid));  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect got state, fd=%d\n",state->devpoll_fd));  // Get itemarray  cls = (*env)->GetObjectClass(env, this);  fid = (*env)->GetFieldID(env, cls, "itemarr", "[Lninja2/core/io_core/nbio/SelectItem;");  itemarr = (jobjectArray)((*env)->GetObjectField(env, this, fid));  if (itemarr == NULL) {    // This can happen if we have an empty SelectSet     return 0;  }  itemarrlen = (*env)->GetArrayLength(env, itemarr);  if (itemarrlen <= 0) {    THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "SelectItem[] array has size <= 0");    return 0;  }  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect got itemarr, len %d\n",itemarrlen));  // Get retitemarr  fid = (*env)->GetFieldID(env, cls, "retevents", "[Lninja2/core/io_core/nbio/SelectItem;");  retitemarr = (jobjectArray)((*env)->GetObjectField(env, this, fid));  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect got retitemarr, length %d\n", ((*env)->GetArrayLength(env, retitemarr))));  // Get fid_revents  cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem");  fid_revents = (*env)->GetFieldID(env, cls, "revents", "S");  fid_fd = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;");  // Get fid2  cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor");  fid2 = (*env)->GetFieldID(env, cls2, "fd", "I");  // Fill in dopoll  dopoll.dp_timeout = timeout;  dopoll.dp_nfds = state->max_retevents;  dopoll.dp_fds = state->retevents;  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect doing DP_POLL\n"));  ret = ioctl(state->devpoll_fd, DP_POLL, &dopoll);  DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect DP_POLL returned %d\n", ret));  if (ret == 0) {    return 0;  }  if (ret < 0) {    int myerrno = errno;    // Don't throw an exception if we were interrupted    if (myerrno != EINTR) {      THROW_EXCEPTION(env, "java/io/IOException", strerror(myerrno));    }     return 0;  }  count = 0;  for (i = 0; i < ret; i++) {    pfd = &(state->retevents[i]);    DEBUG(fprintf(stderr,"SelectSetDevPollImpl.doSelect ret[%d] fd %d revents 0x%x\n", i, pfd->fd, pfd->revents));    retfd = pfd->fd;#ifdef USE_BTREE    data = btree_search(state->tree, retfd);    if (data == NULL) {      THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "retfd not found in registered set");      return 0;    }    selitemobj = (jobject)data;#else     if ((retfd < 0) || (retfd >= MAX_FDS)) {      fprintf(stderr,"Warning: retfd is %d, out of range 0...%d.\n",MAX_FDS);      fprintf(stderr,"  You need to recompile nbio.c with a larger MAX_FDS value.\n");      THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "retfd out of range");      return 0;    }    selitemobj = state->selitems[retfd];    if (selitemobj == (jobject)NULL) {      THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "retfd not found in registered set");      return 0;    }#endif    DEBUG(fprintf(stderr,"Got selitemobj 0x%lx\n", (unsigned long)selitemobj));    realevents = 0;    if (pfd->revents & (POLLIN | POLLPRI)) {      realevents |= SELECTABLE_READ_READY;    }    if (pfd->revents & POLLOUT) {      realevents |= SELECTABLE_WRITE_READY;    }    if (pfd->revents & (POLLERR | POLLHUP | POLLNVAL)) {      realevents |= SELECTABLE_SELECT_ERROR;    }    (*env)->SetShortField(env, selitemobj, fid_revents, realevents);    DEBUG(fprintf(stderr,"Set revents\n"));    (*env)->SetObjectArrayElement(env, retitemarr, count, selitemobj);    DEBUG(fprintf(stderr,"Set retitemarr[%d]\n", count));    count++;  }  return ret;}#endif /* HAS_DEVPOLL *//* SelectSetPollImpl *******************************************************/JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_SelectSetPollImpl_doSelect(JNIEnv *env, jobject this, jint timeout) {  jclass cls, cls2;  jfieldID fid, fid2, fid_events, fid_revents;  jobjectArray itemarr;  jobject selitemobj, fdobj;  struct pollfd *ufds;  int *ufds_map;  int itemarrlen;  int i, n;  int ret;  int num_ufds = 0;  short events, realevents;  DEBUG(fprintf(stderr,"NBIO: doSelect called\n"));  cls = (*env)->GetObjectClass(env, this);  fid = (*env)->GetFieldID(env, cls, "itemarr", "[Lninja2/core/io_core/nbio/SelectItem;");  itemarr = (jobjectArray)(*env)->GetObjectField(env, this, fid);  if (itemarr == NULL) {    // This can happen if we have an empty SelectSet     return 0;  }  DEBUG(fprintf(stderr,"NBIO: doSelect: got itemarr\n"));  itemarrlen = (*env)->GetArrayLength(env, itemarr);  if (itemarrlen <= 0) {    THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "SelectItem[] array has size <= 0");    return 0;  }  DEBUG(fprintf(stderr,"NBIO: doSelect: itemarrlen is %d\n", itemarrlen));  cls = (*env)->FindClass(env, "ninja2/core/io_core/nbio/SelectItem");  DEBUG(fprintf(stderr,"NBIO: doSelect: got SelectItem class\n"));    fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;");  fid_events = (*env)->GetFieldID(env, cls, "events", "S");  fid_revents = (*env)->GetFieldID(env, cls, "revents", "S");  cls2 = (*env)->FindClass(env, "ninja2/core/io_core/nbio/NBIOFileDescriptor");  fid2 = (*env)->GetFieldID(env, cls2, "fd", "I");  // Only allocate a ufd if events != 0  for (i = 0; i < itemarrlen; i++) {    selitemobj = (*env)->GetObjectArrayElement(env, itemarr, i);    if (selitemobj == NULL) {      fprintf(stderr,"NBIO: WARNING: itemarr[%d] is NULL! (itemarrlen=%d)\n", i, itemarrlen);      THROW_EXCEPTION(env, "java/lang/NullPointerException", "SelectItem element is null");      return 0;    }    events = (*env)->GetShortField(env, selitemobj, fid_events);    if (events != 0) num_ufds++;  }  if (num_ufds == 0) return 0;  ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_ufds);  if (ufds == NULL) {    THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "cannot allocate pollfd array");    return 0;  }  DEBUG(fprintf(stderr,"NBIO: doSelect: allocated %d ufds\n", num_ufds));  ufds_map = (int *)malloc(sizeof(int) * num_ufds);  if (ufds_map == NULL) {    THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "cannot allocate ufds_map");    free(ufds);    return 0;  }      n = 0;  for (i = 0; i < itemarrlen; i++) {    selitemobj = (*env)->GetObjectArrayElement(env, itemarr, i);    if (selitemobj == NULL) {      THROW_EXCEPTION(env, "java/lang/NullPointerException", "SelectItem element is null");      free(ufds);      free(ufds_map);      return 0;    }    realevents = 0;    events = (*env)->GetShortField(env, selitemobj, fid_events);    if (events != 0) {      if (events & SELECTABLE_READ_READY) {        realevents |= (POLLIN | POLLPRI);      }      if (events & SELECTABLE_WRITE_READY) {        realevents |= POLLOUT;      }      ufds[n].events = realevents;      DEBUG(fprintf(stderr,"NBIO: doSelect: ufds[%d].events is 0x%x\n", n, ufds[n].events));      ufds[n].revents = 0;      fdobj = (*env)->GetObjectField(env, selitemobj, fid);      ufds[n].fd = (*env)->GetIntField(env, fdobj, fid2);      DEBUG(fprintf(stderr,"NBIO: doSelect: ufds[%d].fd is %d\n", n, ufds[n].fd));      ufds_map[n] = i;      n++;    }  }  /* XXX MDW: poll() is interruptible. Under Linux, a signal (say, from    * the GC) might interrupt poll. For now I don't deal with this   * properly - I just go ahead and return early from doSelect() if the    * call was interrupted.   */  DEBUG(fprintf(stderr,"NBIO: Doing poll, %d fds, timeout %d\n", n, timeout));  ret = nbio_real_poll(ufds, num_ufds, timeout);  DEBUG(fprintf(stderr,"NBIO: doSelect: did poll, timeout %d, ret is %d, errno is %d\n", timeout, ret, errno));  if (ret == 0) {    free(ufds);    free(ufds_map);    return 0;  }  if (ret < 0) {    int myerrno = errno;    // Don't throw an exception if we were interrupted    if (myerrno != EINTR) {      THROW_EXCEPTION(env, "java/io/IOException", strerror(myerrno));    }     free(ufds);    free(ufds_map);    return 0;  }  for (n = 0; n < num_ufds; n++) {    DEBUG(fprintf(stderr,"NBIO: doSelect: ufds[%d].revents is 0x%x\n", n, ufds[n].revents));    if (ufds[n].revents != 0) {      i = ufds_map[n];      selitemobj = (*env)->GetObjectArrayElement(env, itemarr, i);      if (selitemobj == NULL) {        THROW_EXCEPTION(env, "java/lang/NullPointerException", "SelectItem element is null");        free(ufds);        free(ufds_map);        return 0;      }      realevents = 0;      if (ufds[n].revents & (POLLIN | POLLPRI)) {        realevents |= SELECTABLE_READ_READY;      }      if (ufds[n].revents & POLLOUT) {        realevents |= SELECTABLE_WRITE_READY;      }      if (ufds[n].revents & (POLLERR | POLLHUP | POLLNVAL)) {        realevents |= SELECTABLE_SELECT_ERROR;      }      DEBUG(fprintf(stderr,"NBIO: doSelect: setting itemarr[%d].revents to 0x%x\n", i, realevents));      (*env)->SetShortField(env, selitemobj, fid_revents, realevents);    }  }  free(ufds);  free(ufds_map);  DEBUG(fprintf(stderr,"NBIO: doSelect: returning %d\n", ret));  return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -