[pypy-svn] r27376 - pypy/dist/pypy/module/stackless/test

stephan at codespeak.net stephan at codespeak.net
Wed May 17 21:11:07 CEST 2006


Author: stephan
Date: Wed May 17 21:11:05 2006
New Revision: 27376

Modified:
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
removed explicit scheduler (will be probably reintroduced later).


Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Wed May 17 21:11:05 2006
@@ -21,6 +21,8 @@
 This is a necessary Stackless 3.1 feature.
 """
 
+last_thread_id = 0
+
 class TaskletProxy(object):
     def __init__(self, coro):
         self.alive = False
@@ -41,6 +43,12 @@
         self.tempval = None
         self._coro = coro
 
+    def __str__(self):
+        return 'Tasklet-%s' % self.thread_id
+
+    def __getattr__(self,attr):
+        return getattr(self._coro,attr)
+
 class bomb(object):
     """
     A bomb object is used to hold exceptions in tasklets.
@@ -146,15 +154,73 @@
 
 # end interface
 
+def _next():
+    c = getcurrent()
+    if c.next is c:
+        return c
+    nt = c.next
+    if nt is main_tasklet and nt.next is not c:
+        return nt.next
+    else:
+        return nt
+
+def _insert(other):
+    "put other on the end tasklet queue"
+    this = getcurrent()
+    #print '_insert:',this,
+    #_print_queue()
+    prev = this.prev
+    this.prev = other
+    other.next = this
+    other.prev = prev
+    prev.next = other
+    other.blocked = False
+
+def _priority_insert(other):
+    "other will be the next tasklet"
+    this = getcurrent()
+    #print '_priority_insert:',this,
+    #_print_queue()
+    next = this.next
+    this.next = other
+    other.prev = this
+    other.next = next
+    next.prev = other
+    other.blocked = False
+
+def _remove(this):
+    #print '_remove:',this,
+    #_print_queue()
+    if this.next is this:
+        return
+    t = c = getcurrent()
+    count = 0
+    while t is not this:
+        if t is c and count:
+            break
+        count += 1
+        t = t.next
+    this.next.prev = this.prev
+    this.prev.next = this.next
+
+def _print_queue():
+    c = s = getcurrent()
+    print '[',c,
+    while c.next is not s:
+        c = c.next
+        print c,
+    print ']'
+
 main_tasklet = None
 main_coroutine = None
-scheduler = None
 
 def __init():
     global main_tasklet
     global main_coroutine
     main_coroutine = c = coroutine.getcurrent()
     main_tasklet = TaskletProxy(c)
+    main_tasklet.next = main_tasklet.prev = main_tasklet
+    main_tasklet.is_main = True
 
 note = """
 It is not needed to implement the watchdog feature right now.
@@ -181,6 +247,7 @@
 This will create unwanted attributes, but they will
 go away when we port this to interp-leve.
 """
+
 def getcurrent():
     """
     getcurrent() -- return the currently executing tasklet.
@@ -195,14 +262,28 @@
 def getmain():
     return main_tasklet
 
-def schedule():
+def schedule(retval=None):
     """
     schedule(retval=stackless.current) -- switch to the next runnable tasklet.
     The return value for this call is retval, with the current
     tasklet as default.
     schedule_remove(retval=stackless.current) -- ditto, and remove self.
     """
-    scheduler.schedule()
+    #print 'schedule: before switch',
+    #_print_queue()
+    curr = getcurrent()
+    curr.is_current = False
+    nt = _next()
+    if curr.blocked:
+        _remove(curr)
+    nt.is_current = True
+    nt.switch()
+    #print 'schedule: after switch',
+    #_print_queue()
+    if retval is None:
+        return getcurrent()
+    else:
+        return retval
 
 """
 /***************************************************************************
@@ -281,6 +362,7 @@
         return super(tasklet,cls).__new__(cls)
 
     def __init__(self, func=None):
+        global last_thread_id
         super(tasklet,self).__init__()
         self.alive = False
         self.atomic = False
@@ -296,7 +378,8 @@
         self.recursion_depth = 0
         self.restorable = False
         self.scheduled = False
-        self.thread_id = 0
+        last_thread_id += 1
+        self.thread_id = last_thread_id
         self.tempval = None
         if func is not None:
             self.bind(func)
@@ -305,6 +388,9 @@
         self.setup(*argl, **argd)
         return self
 
+    def __str__(self):
+        return 'Tasklet-%s' % self.thread_id
+
     def bind(self, func):
         """
         Binding a tasklet to a callable object.
@@ -323,7 +409,7 @@
         given that it isn't blocked.
         Blocked tasklets need to be reactivated by channels.
         """
-        scheduler.insert(self)
+        _insert(self)
 
     ## note: this is needed. please call coroutine.kill()
     def kill(self):
@@ -354,14 +440,15 @@
         unwanted side-effects. Therefore it is recommended to either run 
         tasklets to the end or to explicitly kill() them.
         """
-        scheduler.remove(self)
+        _remove(self)
 
     def run(self):
         """
         Run this tasklet, given that it isn't blocked.
         Blocked tasks need to be reactivated by channels.
         """
-        scheduler.setnexttask(self)
+        _remove(self)
+        _priority_insert(self)
         ## note: please support different schedulers
         ## and don't mix calls to module functions with scheduler methods.
         schedule()
@@ -544,12 +631,13 @@
             wt = self.queue.popleft()
             retval = wt.tempval
             wt.tempval = None
-            scheduler.insert(wt)
+            _insert(wt)
             self.balance -= 1
             return retval
         else: # Receiving 2
             ct = getcurrent()
-            scheduler.remove(ct)
+            #_remove(ct)
+            ct.blocked = True
             self.queue.append(ct)
             self.balance -= 1
             schedule()
@@ -571,11 +659,12 @@
         if self.balance < 0: # Sending 1
             wt = self.queue.popleft()
             wt.tempval = msg
-            scheduler.priorityinsert(wt)
+            _priority_insert(wt)
             self.balance += 1
         else: # Sending 2
             ct.tempval = msg
-            scheduler.remove(ct)
+            #_remove(ct)
+            ct.blocked = True
             self.queue.append(ct)
             self.balance += 1
         schedule()
@@ -600,74 +689,5 @@
         """
         pass
 
-
-class Scheduler(object):
-    def __init__(self):
-        ## note: better use a deque
-        self.tasklist = []
-        ## note: in terms of moving to interplevel, I would not do that
-        self.nexttask = None 
-
-    def empty(self):
-        return not self.tasklist
-
-    def __str__(self):
-        return repr(self.tasklist) + '/%s' % self.nexttask
-
-    def insert(self,task):
-        if (task not in self.tasklist) and task is not main_tasklet:
-            self.tasklist.append(task)
-        if self.nexttask is None:
-            self.nexttask = 0
-
-    def priorityinsert(self,task):
-        if task in self.tasklist:
-            self.tasklist.remove(task)
-        if task is main_tasklet:
-            return
-        if self.nexttask:
-            self.tasklist.insert(self.nexttask,task)
-        else:
-            self.tasklist.insert(0,task)
-            self.nexttask = 0
-
-    def remove(self,task):
-        try:
-            i = self.tasklist.index(task)
-            del(self.tasklist[i])
-            if self.nexttask > i:
-                self.nexttask -= 1
-            if len(self.tasklist) == 0:
-                self.nexttask = None
-        except ValueError:pass
-
-    def next(self):
-        if self.nexttask is not None:
-            task = self.tasklist[self.nexttask]
-            self.nexttask += 1
-            if self.nexttask == len(self.tasklist):
-                self.nexttask = 0
-            return task
-        else:
-            return main_tasklet
-
-    def setnexttask(self,task):
-        if task not in self.tasklist:
-            self.tasklist.insert(task)
-        try:
-            ## note: this is inefficient
-            ## please use the flag attributes
-            ## a tasklet 'knows' if it is in something
-            i = self.tasklist.index(task)
-            self.nexttask = i
-        except IndexError:pass
-
-    def schedule(self):
-        n = self.next()
-        n.switch()
-
-scheduler = Scheduler()
 __init()
 
-## note: nice work :-)
-



More information about the Pypy-commit mailing list