Commit bbcf9904 authored by Kai Willadsen's avatar Kai Willadsen

Fix support for 'threaded' diff by using threads on Windows

Rather than try to make this code multiprocessing-safe on Windows, this
patch just moves to using a thread pool on Windows, and move code
around to make this cleaner.
parent 2244954e
...@@ -19,13 +19,14 @@ ...@@ -19,13 +19,14 @@
import codecs import codecs
import copy import copy
import functools import functools
import multiprocessing
import os import os
from gettext import gettext as _ from gettext import gettext as _
import signal
import sys
import time import time
from multiprocessing import Pool
from multiprocessing.pool import ThreadPool
import pango import pango
import glib import glib
import gobject import gobject
...@@ -50,21 +51,6 @@ from .util.compat import text_type ...@@ -50,21 +51,6 @@ from .util.compat import text_type
from .util.sourceviewer import srcviewer from .util.sourceviewer import srcviewer
def init_worker():
signal.signal(signal.SIGINT, signal.SIG_IGN)
def matcher_worker(text1, textn):
matcher = matchers.InlineMyersSequenceMatcher(None, text1, textn)
return matcher.get_opcodes()
# maxtasksperchild is new in Python 2.7; for 2.6 compat we do this
try:
process_pool = multiprocessing.Pool(None, init_worker, maxtasksperchild=1)
except TypeError:
process_pool = multiprocessing.Pool(None, init_worker)
class CachedSequenceMatcher(object): class CachedSequenceMatcher(object):
"""Simple class for caching diff results, with LRU-based eviction """Simple class for caching diff results, with LRU-based eviction
...@@ -73,7 +59,20 @@ class CachedSequenceMatcher(object): ...@@ -73,7 +59,20 @@ class CachedSequenceMatcher(object):
eviction is overly simplistic, but is okay for our usage pattern. eviction is overly simplistic, but is okay for our usage pattern.
""" """
process_pool = None
def __init__(self): def __init__(self):
if self.process_pool is None:
if os.name == "nt":
CachedSequenceMatcher.process_pool = ThreadPool(None)
else:
# maxtasksperchild is new in Python 2.7; this is for 2.6 compat
try:
CachedSequenceMatcher.process_pool = Pool(
None, matchers.init_worker, maxtasksperchild=1)
except TypeError:
CachedSequenceMatcher.process_pool = Pool(
None, matchers.init_worker)
self.cache = {} self.cache = {}
def match(self, text1, textn, cb): def match(self, text1, textn, cb):
...@@ -84,8 +83,9 @@ class CachedSequenceMatcher(object): ...@@ -84,8 +83,9 @@ class CachedSequenceMatcher(object):
def inline_cb(opcodes): def inline_cb(opcodes):
self.cache[(text1, textn)] = [opcodes, time.time()] self.cache[(text1, textn)] = [opcodes, time.time()]
gobject.idle_add(lambda: cb(opcodes)) gobject.idle_add(lambda: cb(opcodes))
process_pool.apply_async(matcher_worker, (text1, textn), self.process_pool.apply_async(matchers.matcher_worker,
callback=inline_cb) (text1, textn),
callback=inline_cb)
def clean(self, size_hint): def clean(self, size_hint):
"""Clean the cache if necessary """Clean the cache if necessary
......
...@@ -17,6 +17,25 @@ ...@@ -17,6 +17,25 @@
from collections import namedtuple from collections import namedtuple
import difflib import difflib
import os
import signal
import sys
# Support re-execing on Windows
if os.name == "nt":
self_path = os.path.realpath(__file__)
self_dir = os.path.abspath(os.path.dirname(self_path))
sys.path[0:0] = [self_dir]
def init_worker():
signal.signal(signal.SIGINT, signal.SIG_IGN)
def matcher_worker(text1, textn):
matcher = InlineMyersSequenceMatcher(None, text1, textn)
return matcher.get_opcodes()
def find_common_prefix(a, b): def find_common_prefix(a, b):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment