[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