[pypy-svn] r22686 - pypy/dist/pypy/module/stackless
tismer at codespeak.net
tismer at codespeak.net
Thu Jan 26 15:20:01 CET 2006
Author: tismer
Date: Thu Jan 26 15:19:59 2006
New Revision: 22686
Added:
pypy/dist/pypy/module/stackless/stackless_flags.py (contents, props changed)
Modified:
pypy/dist/pypy/module/stackless/interp_coroutine.py
Log:
added a compatible flags structure to support Stackless in some future
Modified: pypy/dist/pypy/module/stackless/interp_coroutine.py
==============================================================================
--- pypy/dist/pypy/module/stackless/interp_coroutine.py (original)
+++ pypy/dist/pypy/module/stackless/interp_coroutine.py Thu Jan 26 15:19:59 2006
@@ -7,6 +7,7 @@
from pypy.rpython.rarithmetic import intmask
from pypy.rpython.rstack import yield_current_frame_to_caller
+from pypy.module.stackless.stackless_flags import StacklessFlags
import sys
@@ -138,7 +139,11 @@
def call(self):
self.space.call_args(self.w_func, self.args)
-class AppCoroutine(Coroutine):
+class AppCoroutine(Coroutine, StacklessFlags):
+
+ def __init__(self):
+ Coroutine.__init__(self)
+ self.flags = 0
def descr_method__new__(space, w_subtype):
co = space.allocate_instance(AppCoroutine, w_subtype)
Added: pypy/dist/pypy/module/stackless/stackless_flags.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/stackless/stackless_flags.py Thu Jan 26 15:19:59 2006
@@ -0,0 +1,201 @@
+"""
+basic definitions for tasklet flags.
+For simplicity and compatibility,
+they are defined the same for coroutines,
+even if they are not used.
+
+taken from tasklet_structs.h
+----------------------------
+
+/***************************************************************************
+
+ Tasklet Flag Definition
+ -----------------------
+
+ blocked: The tasklet is either waiting in a channel for
+ writing (1) or reading (-1) or not blocked (0).
+ Maintained by the channel logic. Do not change.
+
+ atomic: If true, schedulers will never switch. Driven by
+ the code object or dynamically, see below.
+
+ ignore_nesting: Allows auto-scheduling, even if nesting_level
+ is not zero.
+
+ autoschedule: The tasklet likes to be auto-scheduled. User driven.
+
+ block_trap: Debugging aid. Whenever the tasklet would be
+ blocked by a channel, an exception is raised.
+
+ is_zombie: This tasklet is almost dead, its deallocation has
+ started. The tasklet *must* die at some time, or the
+ process can never end.
+
+ pending_irq: If set, an interrupt was issued during an atomic
+ operation, and should be handled when possible.
+
+
+ Policy for atomic/autoschedule and switching:
+ ---------------------------------------------
+ A tasklet switch can always be done explicitly by calling schedule().
+ Atomic and schedule are concerned with automatic features.
+
+ atomic autoschedule
+
+ 1 any Neither a scheduler nor a watchdog will
+ try to switch this tasklet.
+
+ 0 0 The tasklet can be stopped on desire, or it
+ can be killed by an exception.
+
+ 0 1 Like above, plus auto-scheduling is enabled.
+
+ Default settings:
+ -----------------
+ All flags are zero by default.
+
+ ***************************************************************************/
+
+typedef struct _tasklet_flags {
+ int blocked: 2;
+ unsigned int atomic: 1;
+ unsigned int ignore_nesting: 1;
+ unsigned int autoschedule: 1;
+ unsigned int block_trap: 1;
+ unsigned int is_zombie: 1;
+ unsigned int pending_irq: 1;
+} PyTaskletFlagStruc;
+"""
+
+from pypy.rpython.rarithmetic import LONG_BIT, intmask
+
+class BitSetDef(object):
+ __slots__ = "_names __dict__ _attrname".split()
+
+ def __init__(self, _attrname):
+ self._names = []
+ self._attrname = _attrname
+
+ def __setattr__(self, key, value):
+ if key not in self.__slots__:
+ assert key not in self.__dict__
+ self._names.append(key)
+ object.__setattr__(self, key, value)
+
+ def __iter__(self):
+ return self._enum_objects()
+
+ def _enum_objects(self):
+ for name in self._names:
+ yield name, getattr(self, name)
+
+# negative values are user-writable
+flags = BitSetDef("flags")
+flags.blocked = 2, """writing (1) or reading (-1) or not blocked (0)"""
+flags.atomic = -1, """If true, schedulers will never switch"""
+flags.ignore_nesting = -1, """allow auto-scheduling in nested interpreters"""
+flags.autoschedule = -1, """enable auto-scheduling"""
+flags.block_trap = -1, """raise an exception instead of blocking"""
+flags.is_zombie = 1, """__del__ is in progress"""
+flags.pending_irq = 1, """an interrupt occured while being atomic"""
+
+def make_get_bits(name, bits, shift):
+ """ return a bool for single bits, signed int otherwise """
+ signmask = 1 << (bits - 1 + shift)
+ lshift = bits + shift
+ rshift = bits
+ if bits == 1:
+ return "bool(%s & 0x%x)" % (name, signmask)
+ else:
+ return "intmask(%s << (LONG_BIT-%d)) >> (LONG_BIT-%d)" % (name, lshift, rshift)
+
+def make_set_bits(name, bits, shift):
+ datamask = int('1' * bits, 2)
+ clearmask = datamask << shift
+ return "%s & ~0x%x | (value & 0x%x) << %d" % (name, clearmask, datamask, shift)
+
+def gen_code():
+ from cStringIO import StringIO
+ f = StringIO()
+ print >> f, "class StacklessFlags(object):"
+ print >> f, " _mixin_ = True"
+ shift = 0
+ field = "self.%s" % flags._attrname
+ for name, (bits, doc) in flags:
+ write, bits = bits < 0, abs(bits)
+ print >> f
+ print >> f, ' def get_%s(self):' % name
+ print >> f, ' """%s"""' % doc
+ print >> f, ' return %s' % make_get_bits(field, bits, shift)
+ print >> f, ' def set_%s(self, value):' % name
+ print >> f, ' """%s"""' % doc
+ print >> f, ' %s = %s' % (field, make_set_bits(field, bits, shift))
+ print >> f, ' set_%s._public = %s' % (name, write)
+ shift += bits
+ return f.getvalue()
+
+# BEGIN generated code
+class StacklessFlags(object):
+ _mixin_ = True
+
+ def get_blocked(self):
+ """writing (1) or reading (-1) or not blocked (0)"""
+ return intmask(self.flags << (LONG_BIT-2)) >> (LONG_BIT-2)
+ def set_blocked(self, value):
+ """writing (1) or reading (-1) or not blocked (0)"""
+ self.flags = self.flags & ~0x3 | (value & 0x3) << 0
+ set_blocked._public = False
+
+ def get_atomic(self):
+ """If true, schedulers will never switch"""
+ return bool(self.flags & 0x4)
+ def set_atomic(self, value):
+ """If true, schedulers will never switch"""
+ self.flags = self.flags & ~0x4 | (value & 0x1) << 2
+ set_atomic._public = True
+
+ def get_ignore_nesting(self):
+ """allow auto-scheduling in nested interpreters"""
+ return bool(self.flags & 0x8)
+ def set_ignore_nesting(self, value):
+ """allow auto-scheduling in nested interpreters"""
+ self.flags = self.flags & ~0x8 | (value & 0x1) << 3
+ set_ignore_nesting._public = True
+
+ def get_autoschedule(self):
+ """enable auto-scheduling"""
+ return bool(self.flags & 0x10)
+ def set_autoschedule(self, value):
+ """enable auto-scheduling"""
+ self.flags = self.flags & ~0x10 | (value & 0x1) << 4
+ set_autoschedule._public = True
+
+ def get_block_trap(self):
+ """raise an exception instead of blocking"""
+ return bool(self.flags & 0x20)
+ def set_block_trap(self, value):
+ """raise an exception instead of blocking"""
+ self.flags = self.flags & ~0x20 | (value & 0x1) << 5
+ set_block_trap._public = True
+
+ def get_is_zombie(self):
+ """__del__ is in progress"""
+ return bool(self.flags & 0x40)
+ def set_is_zombie(self, value):
+ """__del__ is in progress"""
+ self.flags = self.flags & ~0x40 | (value & 0x1) << 6
+ set_is_zombie._public = False
+
+ def get_pending_irq(self):
+ """an interrupt occured while being atomic"""
+ return bool(self.flags & 0x80)
+ def set_pending_irq(self, value):
+ """an interrupt occured while being atomic"""
+ self.flags = self.flags & ~0x80 | (value & 0x1) << 7
+ set_pending_irq._public = False
+
+# END generated code
+
+if __name__ == '__main__':
+ # paste this into the file
+ print gen_code()
\ No newline at end of file
More information about the Pypy-commit
mailing list