473,386 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Doubts about how implementing asynchronous timeouts through a heap

Hi,
I'm trying to implement an asynchronous scheduler for asyncore to call
functions at a later time without blocking the main loop.
The logic behind it consists in:

- adding the scheduled functions into a heapified list
- calling a "scheduler" function at every loop which checks the
scheduled functions due to expire soonest

Note that, by using a heap, the first element of the list is always
supposed to be the one with the lower timeout.
Here's the code I wrote:
<--- snippet --->
import heapq
import time
import sys

delayed_map = []

class delayed_call:
"""Calls a function at a later time.

The instance returned is an object that can be used to cancel the
scheduled call, by calling its cancel() method.
It also may be rescheduled by calling delay() or reset()} methods.
"""

def __init__(self, delay, target, *args, **kwargs):
"""
- delay: the number of seconds to wait
- target: the callable object to call later
- args: the arguments to call it with
- kwargs: the keyword arguments to call it with
"""
assert callable(target), "%s is not callable" %target
assert sys.maxint >= delay >= 0, "%s is not greater than or
equal " \
"to 0 seconds" % (delay)
self.__delay = delay
self.__target = target
self.__args = args
self.__kwargs = kwargs
# seconds from the epoch at which to call the function
self.timeout = time.time() + self.__delay
self.cancelled = False
heapq.heappush(delayed_map, self)

def __le__(self, other):
return self.timeout <= other.timeout

def active(self):
"""Return True if this scheduler has not been cancelled."""
return not self.cancelled

def call(self):
"""Call this scheduled function."""
self.__target(*self.__args, **self.__kwargs)

def reset(self):
"""Reschedule this call resetting the current countdown."""
assert not self.cancelled, "Already cancelled"
self.timeout = time.time() + self.__delay
if delayed_map[0] is self:
heapq.heapify(delayed_map)

def delay(self, seconds):
"""Reschedule this call for a later time."""
assert not self.cancelled, "Already cancelled."
assert sys.maxint >= seconds >= 0, "%s is not greater than or
equal " \
"to 0 seconds" %(seconds)
self.__delay = seconds
self.reset()

def cancel(self):
"""Unschedule this call."""
assert not self.cancelled, "Already cancelled"
del self.__target, self.__args, self.__kwargs
if self in delayed_map:
if delayed_map[0] is self:
delayed_map.remove(self)
heapq.heapify(delayed_map)
else:
delayed_map.remove(self)
self.cancelled = True
def fun(arg):
print arg

a = delayed_call(0.6, fun, '0.6')
b = delayed_call(0.5, fun, '0.5')
c = delayed_call(0.4, fun, '0.4')
d = delayed_call(0.3, fun, '0.3')
e = delayed_call(0.2, fun, '0.2')
f = delayed_call(0.1, fun, '0.1')
while delayed_map:
now = time.time()
while delayed_map and now >= delayed_map[0].timeout:
delayed = heapq.heappop(delayed_map)
try:
delayed.call()
finally:
if not delayed.cancelled:
delayed.cancel()
time.sleep(0.01)
</--- snippet --->
Here comes the questions.
Since that the timeouts of the scheduled functions contained in the
list can change when I reset() or cancel() them I don't know exactly
*when* the list needs to be heapified().
By doing some tests I came to the conclusion that I need the heapify()
the list only when the function I reset() or cancel() is the *first of
the list* but I'm not absolutely sure about it.
When do you think it would be necessary calling heapify()?
I wrote a short test suite which tests the code above and I didn't
notice strange behaviors but since that I don't know much about the
logic behind heaps I'd need some help.
Thanks a lot in advance.
--- Giampaolo
http://code.google.com/p/pyftpdlib/
Jul 9 '08 #1
4 1198
On Jul 9, 4:13*am, "Giampaolo Rodola'" <gne...@gmail.comwrote:
Hi,
I'm trying to implement an asynchronous scheduler for asyncore to call
functions at a later time without blocking the main loop.
The logic behind it consists in:

- adding the scheduled functions into a heapified list
- calling a "scheduler" function at every loop which checks the
scheduled functions due to expire soonest

Note that, by using a heap, the first element of the list is always
supposed to be the one with the lower timeout.
Here's the code I wrote:

<--- snippet --->
import heapq
import time
import sys

delayed_map = []

class delayed_call:
* * """Calls a function at a later time.

* * The instance returned is an object that can be used to cancel the
* * scheduled call, by calling its cancel() method.
* * It also may be rescheduled by calling delay() or reset()} methods..
* * """

* * def __init__(self, delay, target, *args, **kwargs):
* * * * """
* * * * - delay: the number of seconds to wait
* * * * - target: the callable object to call later
* * * * - args: the arguments to call it with
* * * * - kwargs: the keyword arguments to call it with
* * * * """
* * * * assert callable(target), "%s is not callable" %target
* * * * assert sys.maxint >= delay >= 0, "%s is not greater than or
equal " \
* * * * * * * * * * * * * * * * * * * * * *"to 0 seconds" % (delay)
* * * * self.__delay = delay
* * * * self.__target = target
* * * * self.__args = args
* * * * self.__kwargs = kwargs
* * * * # seconds from the epoch at which to call the function
* * * * self.timeout = time.time() + self.__delay
* * * * self.cancelled = False
* * * * heapq.heappush(delayed_map, self)

* * def __le__(self, other):
* * * * return self.timeout <= other.timeout

* * def active(self):
* * * * """Return True if this scheduler has not been cancelled."""
* * * * return not self.cancelled

* * def call(self):
* * * * """Call this scheduled function."""
* * * * self.__target(*self.__args, **self.__kwargs)

* * def reset(self):
* * * * """Reschedule this call resetting the current countdown."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * self.timeout = time.time() + self.__delay
* * * * if delayed_map[0] is self:
* * * * * * heapq.heapify(delayed_map)

* * def delay(self, seconds):
* * * * """Reschedule this call for a later time."""
* * * * assert not self.cancelled, "Already cancelled."
* * * * assert sys.maxint >= seconds >= 0, "%s is not greaterthan or
equal " \
* * * * * * * * * * * * * * * * * * * * * *"to 0 seconds" %(seconds)
* * * * self.__delay = seconds
* * * * self.reset()

* * def cancel(self):
* * * * """Unschedule this call."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * del self.__target, self.__args, self.__kwargs
* * * * if self in delayed_map:
* * * * * * if delayed_map[0] is self:
* * * * * * * * delayed_map.remove(self)
* * * * * * * * heapq.heapify(delayed_map)
* * * * * * else:
* * * * * * * * delayed_map.remove(self)
* * * * self.cancelled = True

def fun(arg):
* * print arg

a = delayed_call(0.6, fun, '0.6')
b = delayed_call(0.5, fun, '0.5')
c = delayed_call(0.4, fun, '0.4')
d = delayed_call(0.3, fun, '0.3')
e = delayed_call(0.2, fun, '0.2')
f = delayed_call(0.1, fun, '0.1')

while delayed_map:
* * now = time.time()
* * while delayed_map and now >= delayed_map[0].timeout:
* * * * delayed = heapq.heappop(delayed_map)
* * * * try:
* * * * * * delayed.call()
* * * * finally:
* * * * * * if not delayed.cancelled:
* * * * * * * * delayed.cancel()
* * time.sleep(0.01)
</--- snippet --->

Here comes the questions.
Since that the timeouts of the scheduled functions contained in the
list can change when I reset() or cancel() them I don't know exactly
*when* the list needs to be heapified().
By doing some tests I came to the conclusion that I need the heapify()
the list only when the function I reset() or cancel() is the *first of
the list* but I'm not absolutely sure about it.
When do you think it would be necessary calling heapify()?
I wrote a short test suite which tests the code above and I didn't
notice strange behaviors but since that I don't know much about the
logic behind heaps I'd need some help.
Thanks a lot in advance.

--- Giampaolohttp://code.google.com/p/pyftpdlib/
According to a quick scan, there is some inefficiencies with your
code. In particular, you don't need to re-heapify if the item you
need to remove is the first item; you only need to heappop().

In any case, if the Python standard library heapq module supported non-
lists as containers, then the pair heap implementation I wrote a
couple years ago would be perfect for this particular task. Because
of the rewriting of heapq in C, without a bit of monkeypatching, we
can't re-use that implementation (which offered insert/remove of
arbitrary entries in the heap in O(logn) time, which is significantly
faster than the O(n) time of your implementation).

What I'm thinking is that we should add a pair heap implementation to
the heapq module (which can cache the pure Python functions if it
needs to use them), which would then allow us to use that (and others
to use it generally), add scheduling, etc.

Regardless, it's a 2.7/3.1 feature, so it's ok if we take it slow.

- Josiah
Jul 10 '08 #2
On Jul 10, 11:30*am, Josiah Carlson <josiah.carl...@gmail.comwrote:
On Jul 9, 4:13*am, "Giampaolo Rodola'" <gne...@gmail.comwrote:
Hi,
I'm trying to implement an asynchronous scheduler for asyncore to call
functions at a later time without blocking the main loop.
The logic behind it consists in:
- adding the scheduled functions into a heapified list
- calling a "scheduler" function at every loop which checks the
scheduled functions due to expire soonest
Note that, by using a heap, the first element of the list is always
supposed to be the one with the lower timeout.
Here's the code I wrote:
<--- snippet --->
import heapq
import time
import sys
delayed_map = []
class delayed_call:
* * """Calls a function at a later time.
* * The instance returned is an object that can be used to cancel the
* * scheduled call, by calling its cancel() method.
* * It also may be rescheduled by calling delay() or reset()} methods.
* * """
* * def __init__(self, delay, target, *args, **kwargs):
* * * * """
* * * * - delay: the number of seconds to wait
* * * * - target: the callable object to call later
* * * * - args: the arguments to call it with
* * * * - kwargs: the keyword arguments to call it with
* * * * """
* * * * assert callable(target), "%s is not callable" %target
* * * * assert sys.maxint >= delay >= 0, "%s is not greaterthan or
equal " \
* * * * * * * * * * * * * * * * * ** * * *"to 0 seconds" % (delay)
* * * * self.__delay = delay
* * * * self.__target = target
* * * * self.__args = args
* * * * self.__kwargs = kwargs
* * * * # seconds from the epoch at which to call the function
* * * * self.timeout = time.time() + self.__delay
* * * * self.cancelled = False
* * * * heapq.heappush(delayed_map, self)
* * def __le__(self, other):
* * * * return self.timeout <= other.timeout
* * def active(self):
* * * * """Return True if this scheduler has not been cancelled.."""
* * * * return not self.cancelled
* * def call(self):
* * * * """Call this scheduled function."""
* * * * self.__target(*self.__args, **self.__kwargs)
* * def reset(self):
* * * * """Reschedule this call resetting the current countdown.."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * self.timeout = time.time() + self.__delay
* * * * if delayed_map[0] is self:
* * * * * * heapq.heapify(delayed_map)
* * def delay(self, seconds):
* * * * """Reschedule this call for a later time."""
* * * * assert not self.cancelled, "Already cancelled."
* * * * assert sys.maxint >= seconds >= 0, "%s is not greater than or
equal " \
* * * * * * * * * * * * * * * * * ** * * *"to 0 seconds" %(seconds)
* * * * self.__delay = seconds
* * * * self.reset()
* * def cancel(self):
* * * * """Unschedule this call."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * del self.__target, self.__args, self.__kwargs
* * * * if self in delayed_map:
* * * * * * if delayed_map[0] is self:
* * * * * * * * delayed_map.remove(self)
* * * * * * * * heapq.heapify(delayed_map)
* * * * * * else:
* * * * * * * * delayed_map.remove(self)
* * * * self.cancelled = True
def fun(arg):
* * print arg
a = delayed_call(0.6, fun, '0.6')
b = delayed_call(0.5, fun, '0.5')
c = delayed_call(0.4, fun, '0.4')
d = delayed_call(0.3, fun, '0.3')
e = delayed_call(0.2, fun, '0.2')
f = delayed_call(0.1, fun, '0.1')
while delayed_map:
* * now = time.time()
* * while delayed_map and now >= delayed_map[0].timeout:
* * * * delayed = heapq.heappop(delayed_map)
* * * * try:
* * * * * * delayed.call()
* * * * finally:
* * * * * * if not delayed.cancelled:
* * * * * * * * delayed.cancel()
* * time.sleep(0.01)
</--- snippet --->
Here comes the questions.
Since that the timeouts of the scheduled functions contained in the
list can change when I reset() or cancel() them I don't know exactly
*when* the list needs to be heapified().
By doing some tests I came to the conclusion that I need the heapify()
the list only when the function I reset() or cancel() is the *first of
the list* but I'm not absolutely sure about it.
When do you think it would be necessary calling heapify()?
I wrote a short test suite which tests the code above and I didn't
notice strange behaviors but since that I don't know much about the
logic behind heaps I'd need some help.
Thanks a lot in advance.
--- Giampaolohttp://code.google.com/p/pyftpdlib/

According to a quick scan, there is some inefficiencies with your
code. *In particular, you don't need to re-heapify if the item you
need to remove is the first item; you only need to heappop().

In any case, if the Python standard library heapq module supported non-
lists as containers, then the pair heap implementation I wrote a
couple years ago would be perfect for this particular task. *Because
of the rewriting of heapq in C, without a bit of monkeypatching, we
can't re-use that implementation (which offered insert/remove of
arbitrary entries in the heap in O(logn) time, which is significantly
faster than the O(n) time of your implementation).

What I'm thinking is that we should add a pair heap implementation to
the heapq module (which can cache the pure Python functions if it
needs to use them), which would then allow us to use that (and others
to use it generally), add scheduling, etc.

Regardless, it's a 2.7/3.1 feature, so it's ok if we take it slow.

*- Josiah
Also...first I need to fix the unittest failures. ;)

- Josiah
Jul 11 '08 #3
On Jul 9, 4:13*am, "Giampaolo Rodola'" <gne...@gmail.comwrote:
Hi,
I'm trying to implement an asynchronous scheduler for asyncore to call
functions at a later time without blocking the main loop.
The logic behind it consists in:

- adding the scheduled functions into a heapified list
- calling a "scheduler" function at every loop which checks the
scheduled functions due to expire soonest

Note that, by using a heap, the first element of the list is always
supposed to be the one with the lower timeout.
Here's the code I wrote:

<--- snippet --->
import heapq
import time
import sys

delayed_map = []

class delayed_call:
* * """Calls a function at a later time.

* * The instance returned is an object that can be used to cancel the
* * scheduled call, by calling its cancel() method.
* * It also may be rescheduled by calling delay() or reset()} methods..
* * """

* * def __init__(self, delay, target, *args, **kwargs):
* * * * """
* * * * - delay: the number of seconds to wait
* * * * - target: the callable object to call later
* * * * - args: the arguments to call it with
* * * * - kwargs: the keyword arguments to call it with
* * * * """
* * * * assert callable(target), "%s is not callable" %target
* * * * assert sys.maxint >= delay >= 0, "%s is not greater than or
equal " \
* * * * * * * * * * * * * * * * * * * * * *"to 0 seconds" % (delay)
* * * * self.__delay = delay
* * * * self.__target = target
* * * * self.__args = args
* * * * self.__kwargs = kwargs
* * * * # seconds from the epoch at which to call the function
* * * * self.timeout = time.time() + self.__delay
* * * * self.cancelled = False
* * * * heapq.heappush(delayed_map, self)

* * def __le__(self, other):
* * * * return self.timeout <= other.timeout

* * def active(self):
* * * * """Return True if this scheduler has not been cancelled."""
* * * * return not self.cancelled

* * def call(self):
* * * * """Call this scheduled function."""
* * * * self.__target(*self.__args, **self.__kwargs)

* * def reset(self):
* * * * """Reschedule this call resetting the current countdown."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * self.timeout = time.time() + self.__delay
* * * * if delayed_map[0] is self:
* * * * * * heapq.heapify(delayed_map)

* * def delay(self, seconds):
* * * * """Reschedule this call for a later time."""
* * * * assert not self.cancelled, "Already cancelled."
* * * * assert sys.maxint >= seconds >= 0, "%s is not greaterthan or
equal " \
* * * * * * * * * * * * * * * * * * * * * *"to 0 seconds" %(seconds)
* * * * self.__delay = seconds
* * * * self.reset()

* * def cancel(self):
* * * * """Unschedule this call."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * del self.__target, self.__args, self.__kwargs
* * * * if self in delayed_map:
* * * * * * if delayed_map[0] is self:
* * * * * * * * delayed_map.remove(self)
* * * * * * * * heapq.heapify(delayed_map)
* * * * * * else:
* * * * * * * * delayed_map.remove(self)
* * * * self.cancelled = True

def fun(arg):
* * print arg

a = delayed_call(0.6, fun, '0.6')
b = delayed_call(0.5, fun, '0.5')
c = delayed_call(0.4, fun, '0.4')
d = delayed_call(0.3, fun, '0.3')
e = delayed_call(0.2, fun, '0.2')
f = delayed_call(0.1, fun, '0.1')

while delayed_map:
* * now = time.time()
* * while delayed_map and now >= delayed_map[0].timeout:
* * * * delayed = heapq.heappop(delayed_map)
* * * * try:
* * * * * * delayed.call()
* * * * finally:
* * * * * * if not delayed.cancelled:
* * * * * * * * delayed.cancel()
* * time.sleep(0.01)
</--- snippet --->

Here comes the questions.
Since that the timeouts of the scheduled functions contained in the
list can change when I reset() or cancel() them I don't know exactly
*when* the list needs to be heapified().
By doing some tests I came to the conclusion that I need the heapify()
the list only when the function I reset() or cancel() is the *first of
the list* but I'm not absolutely sure about it.
When do you think it would be necessary calling heapify()?
I wrote a short test suite which tests the code above and I didn't
notice strange behaviors but since that I don't know much about the
logic behind heaps I'd need some help.
Thanks a lot in advance.

--- Giampaolohttp://code.google.com/p/pyftpdlib/
I dug through my old pair heap implementation, did a little hacking on
heapq, and wrote a task scheduler system that plugs in to asyncore.

To schedule a task, you use:
task = asyncore.schedule_task(schedule, delay, callable, *args,
**kwargs)

Once you have that task object, you can then use:
asyncore.reschedule_task(schedule, delay, task)
asyncore.abs_reschedule_task(schedule, time, task)
... to reschedule the task into the future (or past).

You can also:
asyncore.delete_task(schedule, task)
... to completely remove the task from the scheduler.

Each one of these operations are O(logn), where n is the number of
tasks currently known to the scheduler.

To accommodate the new scheduler, asyncore.loop() now has the
following call signature.
def loop(timeout=30.0, use_poll=False, map=None, count=None,
schedule=None, use_schedule=False):

To try to help prevent poll_fcn() starvation (in the case of long-
running scheduled tasks), the task window execution is set just prior
to the poll_fun() call to be now + .01 seconds. That is, window is
set, poll_fun() is called (which should handle current I/O
operations), and all tasks that are to be completed prior to the end
of the task window (now+.01 seconds, set prior to the poll_fun()
call).

Asyncore objects will not gain a set_scheduler() method, nor will they
gain a schedule keyword argument on instantiation. Why? Because the
scheduler is not required for socket I/O to work properly. If you
want to use the scheduler from your own subclasses,
asyncore.<schedule_fcn>(asyncore.scheduled_tasks, ...) should be
sufficient.

This scheduler can be easily plugged into other systems, and it's
likely that I'll add it as an interactive scheduler to sched.py, put
the pair heap implementation into collections, and call it good.

- Josiah
Jul 12 '08 #4
On Jul 12, 12:16*pm, Josiah Carlson <josiah.carl...@gmail.comwrote:
On Jul 9, 4:13*am, "Giampaolo Rodola'" <gne...@gmail.comwrote:
Hi,
I'm trying to implement an asynchronous scheduler forasyncoreto call
functions at a later time without blocking the main loop.
The logic behind it consists in:
- adding the scheduled functions into a heapified list
- calling a "scheduler" function at every loop which checks the
scheduled functions due to expire soonest
Note that, by using a heap, the first element of the list is always
supposed to be the one with the lower timeout.
Here's the code I wrote:
<--- snippet --->
import heapq
import time
import sys
delayed_map = []
class delayed_call:
* * """Calls a function at a later time.
* * The instance returned is an object that can be used to cancel the
* * scheduled call, by calling its cancel() method.
* * It also may be rescheduled by calling delay() or reset()} methods.
* * """
* * def __init__(self, delay, target, *args, **kwargs):
* * * * """
* * * * - delay: the number of seconds to wait
* * * * - target: the callable object to call later
* * * * - args: the arguments to call it with
* * * * - kwargs: the keyword arguments to call it with
* * * * """
* * * * assert callable(target), "%s is not callable" %target
* * * * assert sys.maxint >= delay >= 0, "%s is not greaterthan or
equal " \
* * * * * * * * * * * * * * * * * ** * * *"to 0 seconds" % (delay)
* * * * self.__delay = delay
* * * * self.__target = target
* * * * self.__args = args
* * * * self.__kwargs = kwargs
* * * * # seconds from the epoch at which to call the function
* * * * self.timeout = time.time() + self.__delay
* * * * self.cancelled = False
* * * * heapq.heappush(delayed_map, self)
* * def __le__(self, other):
* * * * return self.timeout <= other.timeout
* * def active(self):
* * * * """Return True if this scheduler has not been cancelled.."""
* * * * return not self.cancelled
* * def call(self):
* * * * """Call this scheduled function."""
* * * * self.__target(*self.__args, **self.__kwargs)
* * def reset(self):
* * * * """Reschedule this call resetting the current countdown.."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * self.timeout = time.time() + self.__delay
* * * * if delayed_map[0] is self:
* * * * * * heapq.heapify(delayed_map)
* * def delay(self, seconds):
* * * * """Reschedule this call for a later time."""
* * * * assert not self.cancelled, "Already cancelled."
* * * * assert sys.maxint >= seconds >= 0, "%s is not greater than or
equal " \
* * * * * * * * * * * * * * * * * ** * * *"to 0 seconds" %(seconds)
* * * * self.__delay = seconds
* * * * self.reset()
* * def cancel(self):
* * * * """Unschedule this call."""
* * * * assert not self.cancelled, "Already cancelled"
* * * * del self.__target, self.__args, self.__kwargs
* * * * if self in delayed_map:
* * * * * * if delayed_map[0] is self:
* * * * * * * * delayed_map.remove(self)
* * * * * * * * heapq.heapify(delayed_map)
* * * * * * else:
* * * * * * * * delayed_map.remove(self)
* * * * self.cancelled = True
def fun(arg):
* * print arg
a = delayed_call(0.6, fun, '0.6')
b = delayed_call(0.5, fun, '0.5')
c = delayed_call(0.4, fun, '0.4')
d = delayed_call(0.3, fun, '0.3')
e = delayed_call(0.2, fun, '0.2')
f = delayed_call(0.1, fun, '0.1')
while delayed_map:
* * now = time.time()
* * while delayed_map and now >= delayed_map[0].timeout:
* * * * delayed = heapq.heappop(delayed_map)
* * * * try:
* * * * * * delayed.call()
* * * * finally:
* * * * * * if not delayed.cancelled:
* * * * * * * * delayed.cancel()
* * time.sleep(0.01)
</--- snippet --->
Here comes the questions.
Since that the timeouts of the scheduled functions contained in the
list can change when I reset() or cancel() them I don't know exactly
*when* the list needs to be heapified().
By doing some tests I came to the conclusion that I need the heapify()
the list only when the function I reset() or cancel() is the *first of
the list* but I'm not absolutely sure about it.
When do you think it would be necessary calling heapify()?
I wrote a short test suite which tests the code above and I didn't
notice strange behaviors but since that I don't know much about the
logic behind heaps I'd need some help.
Thanks a lot in advance.
--- Giampaolohttp://code.google.com/p/pyftpdlib/

I dug through my old pair heap implementation, did a little hacking on
heapq, and wrote a task scheduler system that plugs in toasyncore.

To schedule a task, you use:
task =asyncore.schedule_task(schedule, delay, callable, *args,
**kwargs)

Once you have that task object, you can then use:asyncore.reschedule_task(schedule, delay, task)asyncore.abs_reschedule_task(schedule, time, task)
... to reschedule the task into the future (or past).

You can also:asyncore.delete_task(schedule, task)
... to completely remove the task from the scheduler.

Each one of these operations are O(logn), where n is the number of
tasks currently known to the scheduler.

To accommodate the new scheduler,asyncore.loop() now has the
following call signature.
def loop(timeout=30.0, use_poll=False, map=None, count=None,
schedule=None, use_schedule=False):

To try to help prevent poll_fcn() starvation (in the case of long-
running scheduled tasks), the task window execution is set just prior
to the poll_fun() call to be now + .01 seconds. *That is, window is
set, poll_fun() is called (which should handle current I/O
operations), and all tasks that are to be completed prior to the end
of the task window (now+.01 seconds, set prior to the poll_fun()
call).

Asyncoreobjects will not gain a set_scheduler() method, nor will they
gain a schedule keyword argument on instantiation. *Why? *Because the
scheduler is not required for socket I/O to work properly. *If you
want to use the scheduler from your own subclasses,asyncore.<schedule_fcn>(asyncore.schedu led_tasks, ...) should be
sufficient.

This scheduler can be easily plugged into other systems, and it's
likely that I'll add it as an interactive scheduler to sched.py, put
the pair heap implementation into collections, and call it good.

*- Josiah
After some personal thought a couple weeks back, I instead added bits
of functionality to sched.py to make all of these features possible,
then using it from asyncore. I discussed why a couple weeks ago on my
blog: http://chouyu-31.livejournal.com/316112.html

- Josiah
Aug 5 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
by: ranjeet.gupta | last post by:
Dear All Below are the few doubts which I got while studying about C 1. Is there any method in C by which we can process the entire string in one unit, 2. Does there exist any way to...
4
by: bernardpace | last post by:
Hi, I am doing as shown below below. Now since for every client that connects a new call is being made, when a client finishes the CloseClientCommunication method is called. In case two...
2
by: mircu | last post by:
Hi, I need a quick solution to make my application behave correctly when one of these timeouts occurs. I have some logic in session_start but when the authentication cookie timeouts the user is...
1
by: org | last post by:
Hi, I'm developing a web service with should be used by an .NET CF2 client and an .NET 2.0 Windows client. I've tried to put all the connection logic into one class, which could be used in...
0
by: Paroxsitic | last post by:
Below is my VB.net 2003 code for simply looking at a page from a website with different users with cookies and a get command. More in the program I use the same technique to post actions to the...
8
by: Richard Maher | last post by:
Hi, I am in a mouseup event for button A and I'd like to disable=false button B before starting some work. Is there anyway that an event for button B can then fire before my event processing for...
21
by: puzzlecracker | last post by:
Problem: I send a lot of requests to the application (running on a different box, of course), and I receive back responses from the app . Below: socket corresponds to Socket socket=new...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.