mirror of
https://github.com/Mikaela/Limnoria.git
synced 2024-11-23 19:19:32 +01:00
Prevent possible race conditions in scheduler.
This commit is contained in:
parent
32eef54a65
commit
9723e14a4d
@ -32,8 +32,11 @@ Schedule plugin with a subclass of drivers.IrcDriver in order to be run as a
|
|||||||
Supybot driver.
|
Supybot driver.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import heapq
|
import heapq
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
import supybot.log as log
|
import supybot.log as log
|
||||||
import supybot.world as world
|
import supybot.world as world
|
||||||
@ -61,8 +64,10 @@ class Schedule(drivers.IrcDriver):
|
|||||||
self.schedule = []
|
self.schedule = []
|
||||||
self.events = {}
|
self.events = {}
|
||||||
self.counter = 0
|
self.counter = 0
|
||||||
|
self.lock = Lock()
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
with self.lock:
|
||||||
self.events.clear()
|
self.events.clear()
|
||||||
self.schedule[:] = []
|
self.schedule[:] = []
|
||||||
# We don't reset the counter here because if someone has held an id of
|
# We don't reset the counter here because if someone has held an id of
|
||||||
@ -82,6 +87,7 @@ class Schedule(drivers.IrcDriver):
|
|||||||
self.counter += 1
|
self.counter += 1
|
||||||
assert name not in self.events, \
|
assert name not in self.events, \
|
||||||
'An event with the same name has already been scheduled.'
|
'An event with the same name has already been scheduled.'
|
||||||
|
with self.lock:
|
||||||
self.events[name] = f
|
self.events[name] = f
|
||||||
heapq.heappush(self.schedule, mytuple((t, name, args, kwargs)))
|
heapq.heappush(self.schedule, mytuple((t, name, args, kwargs)))
|
||||||
return name
|
return name
|
||||||
@ -89,12 +95,13 @@ class Schedule(drivers.IrcDriver):
|
|||||||
def removeEvent(self, name):
|
def removeEvent(self, name):
|
||||||
"""Removes the event with the given name from the schedule."""
|
"""Removes the event with the given name from the schedule."""
|
||||||
f = self.events.pop(name)
|
f = self.events.pop(name)
|
||||||
self.schedule = [x for x in self.schedule if f != name]
|
|
||||||
# We must heapify here because the heap property may not be preserved
|
# We must heapify here because the heap property may not be preserved
|
||||||
# by the above list comprehension. We could, conceivably, just mark
|
# by the above list comprehension. We could, conceivably, just mark
|
||||||
# the elements of the heap as removed and ignore them when we heappop,
|
# the elements of the heap as removed and ignore them when we heappop,
|
||||||
# but that would only save a constant factor (we're already linear for
|
# but that would only save a constant factor (we're already linear for
|
||||||
# the listcomp) so I'm not worried about it right now.
|
# the listcomp) so I'm not worried about it right now.
|
||||||
|
with self.lock:
|
||||||
|
self.schedule = [x for x in self.schedule if f != name]
|
||||||
heapq.heapify(self.schedule)
|
heapq.heapify(self.schedule)
|
||||||
return f
|
return f
|
||||||
|
|
||||||
@ -123,6 +130,7 @@ class Schedule(drivers.IrcDriver):
|
|||||||
'why do we continue to live?')
|
'why do we continue to live?')
|
||||||
time.sleep(1) # We're the only driver; let's pause to think.
|
time.sleep(1) # We're the only driver; let's pause to think.
|
||||||
while self.schedule and self.schedule[0][0] < time.time():
|
while self.schedule and self.schedule[0][0] < time.time():
|
||||||
|
with self.lock:
|
||||||
(t, name, args, kwargs) = heapq.heappop(self.schedule)
|
(t, name, args, kwargs) = heapq.heappop(self.schedule)
|
||||||
f = self.events[name]
|
f = self.events[name]
|
||||||
del self.events[name]
|
del self.events[name]
|
||||||
|
Loading…
Reference in New Issue
Block a user