Add instant autoreload on platforms supporting kqueue.

This commit is contained in:
Aymeric Augustin 2013-10-30 23:08:12 +01:00
parent 8faaf03b86
commit 8f09ec61f8
1 changed files with 45 additions and 0 deletions

View File

@ -65,6 +65,16 @@ try:
except ImportError: except ImportError:
pass pass
try:
import select
select.kevent, select.kqueue
USE_KQUEUE = True
import resource
NOFILES_SOFT, NOFILES_HARD = resource.getrlimit(resource.RLIMIT_NOFILE)
except AttributeError:
USE_KQUEUE = False
RUN_RELOADER = True RUN_RELOADER = True
_mtimes = {} _mtimes = {}
@ -119,6 +129,39 @@ def inotify_code_changed():
# If we are here the code must have changed. # If we are here the code must have changed.
return True return True
def kqueue_code_changed():
"""
Checks for changed code using kqueue. After being called
it blocks until a change event has been fired.
"""
# Maximum number of open file descriptors is typically too low (256).
filenames = list(gen_filenames())
resource.setrlimit(resource.RLIMIT_NOFILE,
(NOFILES_SOFT + len(filenames), NOFILES_HARD))
kqueue = select.kqueue()
fds = [open(filename) for filename in filenames]
_filter = select.KQ_FILTER_VNODE
flags = select.KQ_EV_ADD
fflags = (
select.KQ_NOTE_DELETE |
select.KQ_NOTE_WRITE |
select.KQ_NOTE_EXTEND |
select.KQ_NOTE_ATTRIB |
select.KQ_NOTE_LINK |
select.KQ_NOTE_RENAME |
select.KQ_NOTE_REVOKE
)
kevents = [select.kevent(fd, _filter, flags, fflags) for fd in fds]
kqueue.control(kevents, 1)
for fd in fds:
fd.close()
kqueue.close()
return True
def code_changed(): def code_changed():
global _mtimes, _win global _mtimes, _win
for filename in gen_filenames(): for filename in gen_filenames():
@ -178,6 +221,8 @@ def reloader_thread():
ensure_echo_on() ensure_echo_on()
if USE_INOTIFY: if USE_INOTIFY:
fn = inotify_code_changed fn = inotify_code_changed
elif USE_KQUEUE:
fn = kqueue_code_changed
else: else:
fn = code_changed fn = code_changed
while RUN_RELOADER: while RUN_RELOADER: