""" 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.rlib.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()