[pypy-commit] pypy default: refactor the autoflush of streams: we cannot keep a set of w_iobase instances, else they would be never collected by the GC. Instead, we keep a set of 'holders', which have a weakref to the actual stream. When the stream is closed, the holder is removed from the set
antocuni
noreply at buildbot.pypy.org
Thu Feb 23 16:27:11 CET 2012
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch:
Changeset: r52807:4867e38be6fb
Date: 2012-02-23 16:11 +0100
http://bitbucket.org/pypy/pypy/changeset/4867e38be6fb/
Log: refactor the autoflush of streams: we cannot keep a set of w_iobase
instances, else they would be never collected by the GC. Instead, we
keep a set of 'holders', which have a weakref to the actual stream.
When the stream is closed, the holder is removed from the set
diff --git a/pypy/module/_io/__init__.py b/pypy/module/_io/__init__.py
--- a/pypy/module/_io/__init__.py
+++ b/pypy/module/_io/__init__.py
@@ -39,5 +39,6 @@
def shutdown(self, space):
# at shutdown, flush all open streams. Ignore I/O errors.
- from pypy.module._io.interp_iobase import flush_all_streams
- flush_all_streams(space)
+ from pypy.module._io.interp_iobase import get_autoflushher
+ get_autoflushher(space).flush_all(space)
+
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -5,6 +5,8 @@
from pypy.interpreter.gateway import interp2app
from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.rlib.rstring import StringBuilder
+from pypy.rlib import rweakref
+
DEFAULT_BUFFER_SIZE = 8192
@@ -43,7 +45,8 @@
self.space = space
self.w_dict = space.newdict()
self.__IOBase_closed = False
- register_flushable_stream(space, self)
+ self.streamholder = None # needed by AutoFlusher
+ get_autoflushher(space).add(self)
def getdict(self, space):
return self.w_dict
@@ -99,8 +102,7 @@
space.call_method(self, "flush")
finally:
self.__IOBase_closed = True
- flushable_streams = get_flushable_streams(space)
- del flushable_streams[self]
+ get_autoflushher(space).remove(self)
def flush_w(self, space):
if self._CLOSED():
@@ -312,26 +314,46 @@
# functions to make sure that all streams are flushed on exit
# ------------------------------------------------------------
-class IoState:
+class StreamHolder(object):
+
+ def __init__(self, w_iobase):
+ self.w_iobase_ref = rweakref.ref(w_iobase)
+ w_iobase.autoflusher = self
+
+ def autoflush(self, space):
+ w_iobase = self.w_iobase_ref()
+ if w_iobase is not None:
+ space.call_method(w_iobase, 'flush') # XXX: ignore IOErrors?
+
+
+class AutoFlusher(object):
+
def __init__(self, space):
- self.flushable_streams = {}
+ self.streams = {}
-def get_flushable_streams(space):
- return space.fromcache(IoState).flushable_streams
+ def add(self, w_iobase):
+ assert w_iobase.streamholder is None
+ holder = StreamHolder(w_iobase)
+ w_iobase.streamholder = holder
+ self.streams[holder] = None
-def register_flushable_stream(space, w_stream):
- streams = get_flushable_streams(space)
- streams[w_stream] = None
+ def remove(self, w_iobase):
+ holder = w_iobase.streamholder
+ if holder is not None:
+ del self.streams[holder]
-def flush_all_streams(space):
- flushable_streams = get_flushable_streams(space)
- while flushable_streams:
- for w_stream in flushable_streams.keys():
- assert isinstance(w_stream, W_IOBase)
- try:
- del flushable_streams[w_stream]
- except KeyError:
- pass # key was removed in the meantime
- else:
- space.call_method(w_stream, 'flush') # XXX: ignore IOErrors?
-
+ def flush_all(self, space):
+ while self.streams:
+ for streamholder in self.streams.keys():
+ try:
+ del self.streams[streamholder]
+ except KeyError:
+ pass # key was removed in the meantime
+ else:
+ streamholder.autoflush(space)
+
+
+def get_autoflushher(space):
+ return space.fromcache(AutoFlusher)
+
+
More information about the pypy-commit
mailing list