PageRenderTime 45ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/select/interp_epoll.py

https://bitbucket.org/pypy/pypy/
Python | 193 lines | 154 code | 39 blank | 0 comment | 19 complexity | 2e688d4e98abaad3e5e796514d7f505a MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from __future__ import with_statement
  2. import errno
  3. from pypy.interpreter.baseobjspace import W_Root
  4. from pypy.interpreter.gateway import interp2app, unwrap_spec
  5. from pypy.interpreter.error import OperationError, oefmt
  6. from pypy.interpreter.error import exception_from_saved_errno
  7. from pypy.interpreter.typedef import TypeDef, GetSetProperty
  8. from rpython.rtyper.lltypesystem import lltype, rffi
  9. from rpython.rtyper.tool import rffi_platform
  10. from rpython.rlib._rsocket_rffi import socketclose, FD_SETSIZE
  11. from rpython.rlib.rposix import get_saved_errno
  12. from rpython.rlib.rarithmetic import intmask
  13. from rpython.translator.tool.cbuild import ExternalCompilationInfo
  14. eci = ExternalCompilationInfo(
  15. includes = ['sys/epoll.h']
  16. )
  17. class CConfig:
  18. _compilation_info_ = eci
  19. CConfig.epoll_data = rffi_platform.Struct("union epoll_data", [
  20. ("fd", rffi.INT),
  21. ])
  22. CConfig.epoll_event = rffi_platform.Struct("struct epoll_event", [
  23. ("events", rffi.UINT),
  24. ("data", CConfig.epoll_data)
  25. ])
  26. public_symbols = dict.fromkeys([
  27. "EPOLLIN", "EPOLLOUT", "EPOLLPRI", "EPOLLERR", "EPOLLHUP",
  28. "EPOLLET", "EPOLLONESHOT", "EPOLLRDNORM", "EPOLLRDBAND",
  29. "EPOLLWRNORM", "EPOLLWRBAND", "EPOLLMSG"
  30. ])
  31. for symbol in public_symbols:
  32. setattr(CConfig, symbol, rffi_platform.DefinedConstantInteger(symbol))
  33. for symbol in ["EPOLL_CTL_ADD", "EPOLL_CTL_MOD", "EPOLL_CTL_DEL"]:
  34. setattr(CConfig, symbol, rffi_platform.ConstantInteger(symbol))
  35. cconfig = rffi_platform.configure(CConfig)
  36. for symbol in public_symbols:
  37. public_symbols[symbol] = intmask(cconfig[symbol])
  38. epoll_event = cconfig["epoll_event"]
  39. EPOLL_CTL_ADD = cconfig["EPOLL_CTL_ADD"]
  40. EPOLL_CTL_MOD = cconfig["EPOLL_CTL_MOD"]
  41. EPOLL_CTL_DEL = cconfig["EPOLL_CTL_DEL"]
  42. DEF_REGISTER_EVENTMASK = (public_symbols["EPOLLIN"] |
  43. public_symbols["EPOLLOUT"] |
  44. public_symbols["EPOLLPRI"])
  45. epoll_create = rffi.llexternal(
  46. "epoll_create", [rffi.INT], rffi.INT, compilation_info=eci,
  47. save_err=rffi.RFFI_SAVE_ERRNO
  48. )
  49. epoll_ctl = rffi.llexternal(
  50. "epoll_ctl",
  51. [rffi.INT, rffi.INT, rffi.INT, lltype.Ptr(epoll_event)],
  52. rffi.INT,
  53. compilation_info=eci,
  54. save_err=rffi.RFFI_SAVE_ERRNO
  55. )
  56. epoll_wait = rffi.llexternal(
  57. "epoll_wait",
  58. [rffi.INT, rffi.CArrayPtr(epoll_event), rffi.INT, rffi.INT],
  59. rffi.INT,
  60. compilation_info=eci,
  61. save_err=rffi.RFFI_SAVE_ERRNO
  62. )
  63. class W_Epoll(W_Root):
  64. def __init__(self, space, epfd):
  65. self.epfd = epfd
  66. self.register_finalizer(space)
  67. @unwrap_spec(sizehint=int)
  68. def descr__new__(space, w_subtype, sizehint=-1):
  69. if sizehint == -1:
  70. sizehint = FD_SETSIZE - 1
  71. elif sizehint < 0:
  72. raise oefmt(space.w_ValueError,
  73. "sizehint must be greater than zero, got %d", sizehint)
  74. epfd = epoll_create(sizehint)
  75. if epfd < 0:
  76. raise exception_from_saved_errno(space, space.w_IOError)
  77. return space.wrap(W_Epoll(space, epfd))
  78. @unwrap_spec(fd=int)
  79. def descr_fromfd(space, w_cls, fd):
  80. return space.wrap(W_Epoll(space, fd))
  81. def _finalize_(self):
  82. self.close()
  83. def check_closed(self, space):
  84. if self.get_closed():
  85. raise oefmt(space.w_ValueError, "I/O operation on closed epoll fd")
  86. def get_closed(self):
  87. return self.epfd < 0
  88. def close(self):
  89. if not self.get_closed():
  90. socketclose(self.epfd)
  91. self.epfd = -1
  92. def epoll_ctl(self, space, ctl, w_fd, eventmask, ignore_ebadf=False):
  93. fd = space.c_filedescriptor_w(w_fd)
  94. with lltype.scoped_alloc(epoll_event) as ev:
  95. ev.c_events = rffi.cast(rffi.UINT, eventmask)
  96. rffi.setintfield(ev.c_data, 'c_fd', fd)
  97. result = epoll_ctl(self.epfd, ctl, fd, ev)
  98. if ignore_ebadf and get_saved_errno() == errno.EBADF:
  99. result = 0
  100. if result < 0:
  101. raise exception_from_saved_errno(space, space.w_IOError)
  102. def descr_get_closed(self, space):
  103. return space.wrap(self.get_closed())
  104. def descr_fileno(self, space):
  105. self.check_closed(space)
  106. return space.wrap(self.epfd)
  107. def descr_close(self, space):
  108. self.close()
  109. @unwrap_spec(eventmask=int)
  110. def descr_register(self, space, w_fd, eventmask=DEF_REGISTER_EVENTMASK):
  111. self.check_closed(space)
  112. self.epoll_ctl(space, EPOLL_CTL_ADD, w_fd, eventmask)
  113. def descr_unregister(self, space, w_fd):
  114. self.check_closed(space)
  115. self.epoll_ctl(space, EPOLL_CTL_DEL, w_fd, 0, ignore_ebadf=True)
  116. @unwrap_spec(eventmask=int)
  117. def descr_modify(self, space, w_fd, eventmask):
  118. self.check_closed(space)
  119. self.epoll_ctl(space, EPOLL_CTL_MOD, w_fd, eventmask)
  120. @unwrap_spec(timeout=float, maxevents=int)
  121. def descr_poll(self, space, timeout=-1.0, maxevents=-1):
  122. self.check_closed(space)
  123. if timeout < 0:
  124. timeout = -1.0
  125. else:
  126. timeout *= 1000.0
  127. if maxevents == -1:
  128. maxevents = FD_SETSIZE - 1
  129. elif maxevents < 1:
  130. raise oefmt(space.w_ValueError,
  131. "maxevents must be greater than 0, not %d", maxevents)
  132. with lltype.scoped_alloc(rffi.CArray(epoll_event), maxevents) as evs:
  133. nfds = epoll_wait(self.epfd, evs, maxevents, int(timeout))
  134. if nfds < 0:
  135. raise exception_from_saved_errno(space, space.w_IOError)
  136. elist_w = [None] * nfds
  137. for i in xrange(nfds):
  138. event = evs[i]
  139. elist_w[i] = space.newtuple(
  140. [space.wrap(event.c_data.c_fd), space.wrap(event.c_events)]
  141. )
  142. return space.newlist(elist_w)
  143. W_Epoll.typedef = TypeDef("select.epoll",
  144. __new__ = interp2app(W_Epoll.descr__new__.im_func),
  145. fromfd = interp2app(W_Epoll.descr_fromfd.im_func, as_classmethod=True),
  146. closed = GetSetProperty(W_Epoll.descr_get_closed),
  147. fileno = interp2app(W_Epoll.descr_fileno),
  148. close = interp2app(W_Epoll.descr_close),
  149. register = interp2app(W_Epoll.descr_register),
  150. unregister = interp2app(W_Epoll.descr_unregister),
  151. modify = interp2app(W_Epoll.descr_modify),
  152. poll = interp2app(W_Epoll.descr_poll),
  153. )
  154. W_Epoll.typedef.acceptable_as_base_class = False