[Stackless-checkins] r53840 - stackless/sandbox/examples/scheduleAlternative.py stackless/sandbox/examples/scheduleNormal.py
richard.tew
python-checkins at python.org
Wed Feb 21 19:04:37 CET 2007
Author: richard.tew
Date: Wed Feb 21 19:04:35 2007
New Revision: 53840
Added:
stackless/sandbox/examples/scheduleAlternative.py
stackless/sandbox/examples/scheduleNormal.py
Log:
Two examples meant to illustrate the two approaches to scheduling.
Added: stackless/sandbox/examples/scheduleAlternative.py
==============================================================================
--- (empty file)
+++ stackless/sandbox/examples/scheduleAlternative.py Wed Feb 21 19:04:35 2007
@@ -0,0 +1,114 @@
+#
+# The alternative approach to scheduling.
+#
+# Author: Richard Tew <richard.m.tew at gmail.com>
+#
+# This code was written to serve as an example of Stackless Python usage.
+# Feel free to email me with any questions, comments, or suggestions for
+# improvement.
+#
+# Benefits of this approach:
+#
+# - It lends itself well to embedding, if implemented in C or C++.
+#
+# - It allows more precise control.
+#
+# Limitations of this approach:
+#
+# - The expectation is that the scheduler will be empty because of this
+# will exit pretty much immediately. So anything which calls to
+# 'stackless.schedule' rather than using 'BeNice' or 'Sleep' will
+# break this scheduling model and prevent it from working as
+# expected. After all, if there are tasklets in the scheduler it
+# continues to run and does not exit.
+#
+# Ideally 'stackless.schedule' should be patched to call BeNice. Or
+# calls to it just avoided completely.
+#
+
+import time
+import stackless
+
+yieldChannel = stackless.channel()
+sleepingTasklets = []
+
+# Utility functions for tasklets to call.
+
+def BeNice():
+ """ Signal that the tasklet can be interrupted. """
+ yieldChannel.receive()
+
+def Sleep(secondsToWait):
+ """ Put the current tasklet to sleep for a number of seconds. """
+ channel = stackless.channel()
+ endTime = time.time() + secondsToWait
+ sleepingTasklets.append((endTime, channel))
+ sleepingTasklets.sort()
+ # Block until we get sent an awakening notification.
+ channel.receive()
+
+# Scheduler running related functions.
+
+def CheckSleepingTasklets():
+ """ Awaken all tasklets which are due to be awakened. """
+ while len(sleepingTasklets):
+ endTime = sleepingTasklets[0][0]
+ if endTime > time.time():
+ break
+ channel = sleepingTasklets[0][1]
+ del sleepingTasklets[0]
+ # We have to send something, but it doesn't matter what as it is not used.
+ channel.send(None)
+
+def ScheduleTasklets():
+ # Only schedule as many tasklets as there are waiting when
+ # we start. This is because some of the tasklets we awaken
+ # may BeNice their way back onto the channel. Well they
+ # would
+ n = -yieldChannel.balance
+ while n > 0:
+ yieldChannel.send(None)
+ n -= 1
+
+ CheckSleepingTasklets()
+
+ # Run any tasklets which need to be scheduled. As long as the BeNice and
+ # Sleep callers do not use schedule they should never be in the scheduler
+ # at this point, but rather back in the yield channel or on a sleep channel.
+ # Loosely guessing, I would say that only newly created tasklets should
+ # ever be in the scheduler. And nothing should stay in there for that
+ # long before moving out by using Sleep or BeNice. If something does stay
+ # in there too long then it is not yielding or is keeping the scheduler
+ # running by using 'stackless.schedule' which is not compatible with the
+ # way this method intends the scheduler to be used.
+
+ interruptedTasklet = stackless.run(1000000)
+ if interruptedTasklet:
+ # Should really print a stacktrace from the tasklet so it can be
+ # rewritten to 'be nice'. Alternatively the tasklet could be killed
+ # at this point if that suits the application.
+ interruptedTasklet.insert()
+
+exitScheduler = False
+
+def Run():
+ def Test(n):
+ global exitScheduler
+ while n:
+ if n % 2 == 1:
+ print n, "BeNice"
+ BeNice()
+ else:
+ print n, "Sleep"
+ Sleep(1.0)
+ n -= 1
+ exitScheduler = True
+
+ # Do 10 iterations.
+ stackless.tasklet(Test)(10)
+
+ while not exitScheduler:
+ ScheduleTasklets()
+
+if __name__ == '__main__':
+ Run()
Added: stackless/sandbox/examples/scheduleNormal.py
==============================================================================
--- (empty file)
+++ stackless/sandbox/examples/scheduleNormal.py Wed Feb 21 19:04:35 2007
@@ -0,0 +1,74 @@
+#
+# The normal approach to scheduling.
+#
+# Author: Richard Tew <richard.m.tew at gmail.com>
+#
+# This code was written to serve as an example of Stackless Python usage.
+# Feel free to email me with any questions, comments, or suggestions for
+# improvement.
+#
+# Benefits of this approach:
+#
+# - It is easy to use from the interpreter.
+#
+# Limitations of this approach:
+#
+# - If there are no tasklets that run for the life of the application
+# or script then the scheduler may exit when things are not complete.
+# One example of this is when all tasklets which were in the
+# scheduler and did not complete are waiting on channels.
+#
+
+import time
+import stackless
+
+exitScheduler = False
+
+sleepingTasklets = []
+
+# Utility functions for tasklets to call.
+
+def Sleep(secondsToWait):
+ """ Put the current tasklet to sleep for a number of seconds. """
+ channel = stackless.channel()
+ endTime = time.time() + secondsToWait
+ sleepingTasklets.append((endTime, channel))
+ sleepingTasklets.sort()
+ # Block until we get sent an awakening notification.
+ channel.receive()
+
+# Scheduler running related functions.
+
+def ManageSleepingTasklets():
+ """ Awaken all tasklets which are due to be awakened. """
+ while not exitScheduler:
+ while len(sleepingTasklets):
+ endTime = sleepingTasklets[0][0]
+ if endTime > time.time():
+ break
+ channel = sleepingTasklets[0][1]
+ del sleepingTasklets[0]
+ # It does not matter what we send as it is not used.
+ channel.send(None)
+ stackless.schedule()
+
+
+def Run():
+ def Test(n):
+ global exitScheduler
+ while n:
+ print n, "Sleep"
+ Sleep(1.0)
+ n -= 1
+ exitScheduler = True
+
+ stackless.tasklet(Test)(10)
+ stackless.tasklet(ManageSleepingTasklets)()
+
+ # This will run until there are no scheduled tasklets. But because we
+ # create one to manage the sleeping tasklets this will mean it will run
+ # indefinitely.
+ stackless.run()
+
+if __name__ == '__main__':
+ Run()
_______________________________________________
Stackless-checkins mailing list
Stackless-checkins at stackless.com
http://www.stackless.com/mailman/listinfo/stackless-checkins
More information about the Stackless-checkins
mailing list