From: <am...@us...> - 2009-04-10 15:37:02
|
Revision: 6208 http://jython.svn.sourceforge.net/jython/?rev=6208&view=rev Author: amak Date: 2009-04-10 15:36:58 +0000 (Fri, 10 Apr 2009) Log Message: ----------- Creating a poll object cache for MS Windows, because of a problem on that platform with creating too many Selectors. http://bugs.jython.org/issue1291 Modified Paths: -------------- trunk/jython/Lib/select.py Modified: trunk/jython/Lib/select.py =================================================================== --- trunk/jython/Lib/select.py 2009-04-10 13:45:27 UTC (rev 6207) +++ trunk/jython/Lib/select.py 2009-04-10 15:36:58 UTC (rev 6208) @@ -7,10 +7,11 @@ import java.nio.channels.Selector from java.nio.channels.SelectionKey import OP_ACCEPT, OP_CONNECT, OP_WRITE, OP_READ +import errno +import os +import Queue import socket -import errno - class error(Exception): pass ALL = None @@ -144,10 +145,18 @@ except java.lang.Exception, jlx: raise _map_exception(jlx) - def close(self): + def _deregister_all(self): try: for k in self.selector.keys(): k.cancel() + # Keys are not actually removed from the selector until the next select operation. + self.selector.selectNow() + except java.lang.Exception, jlx: + raise _map_exception(jlx) + + def close(self): + try: + self._deregister_all() self.selector.close() except java.lang.Exception, jlx: raise _map_exception(jlx) @@ -165,10 +174,48 @@ return 0 return int(floatvalue * 1000) # Convert to milliseconds +# This cache for poll objects is required because of a bug in java on MS Windows +# http://bugs.jython.org/issue1291 + +class poll_object_cache: + + def __init__(self): + self.is_windows = os.get_os_type() == 'nt' + if self.is_windows: + self.poll_object_queue = Queue.Queue() + import atexit + atexit.register(self.finalize) + + def get_poll_object(self): + if not self.is_windows: + return poll() + try: + return self.poll_object_queue.get(False) + except Queue.Empty: + return poll() + + def release_poll_object(self, pobj): + if self.is_windows: + pobj._deregister_all() + self.poll_object_queue.put(pobj) + else: + pobj.close() + + def finalize(self): + if self.is_windows: + while True: + try: + p = self.poll_object_queue.get(False) + p.close() + except Queue.Empty: + return + +_poll_object_cache = poll_object_cache() + def native_select(read_fd_list, write_fd_list, outofband_fd_list, timeout=None): timeout = _calcselecttimeoutvalue(timeout) # First create a poll object to do the actual watching. - pobj = poll() + pobj = _poll_object_cache.get_poll_object() try: registered_for_read = {} # Check the read list @@ -192,10 +239,7 @@ write_ready_list.append(fd) return read_ready_list, write_ready_list, oob_ready_list finally: - # Need to close the poll object no matter what happened - # If it is left open, it may still have references to sockets - # That were registered before any exceptions occurred - pobj.close() + _poll_object_cache.release_poll_object(pobj) select = native_select This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |