[meld] Fix support for 'threaded' diff by using threads on Windows



commit bbcf9904b9a2a7656f89908cfe607332fede49e6
Author: Kai Willadsen <kai willadsen gmail com>
Date:   Mon Mar 4 06:18:50 2013 +1000

    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.

 meld/filediff.py |   40 ++++++++++++++++++++--------------------
 meld/matchers.py |   19 +++++++++++++++++++
 2 files changed, 39 insertions(+), 20 deletions(-)
---
diff --git a/meld/filediff.py b/meld/filediff.py
index 36220c1..6bca05f 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -19,13 +19,14 @@
 import codecs
 import copy
 import functools
-import multiprocessing
 import os
 from gettext import gettext as _
-import signal
-import sys
 import time
 
+from multiprocessing import Pool
+from multiprocessing.pool import ThreadPool
+
+
 import pango
 import glib
 import gobject
@@ -50,21 +51,6 @@ from .util.compat import text_type
 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):
     """Simple class for caching diff results, with LRU-based eviction
 
@@ -73,7 +59,20 @@ class CachedSequenceMatcher(object):
     eviction is overly simplistic, but is okay for our usage pattern.
     """
 
+    process_pool = None
+
     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 = {}
 
     def match(self, text1, textn, cb):
@@ -84,8 +83,9 @@ class CachedSequenceMatcher(object):
             def inline_cb(opcodes):
                 self.cache[(text1, textn)] = [opcodes, time.time()]
                 gobject.idle_add(lambda: cb(opcodes))
-            process_pool.apply_async(matcher_worker, (text1, textn),
-                                     callback=inline_cb)
+            self.process_pool.apply_async(matchers.matcher_worker,
+                                          (text1, textn),
+                                          callback=inline_cb)
 
     def clean(self, size_hint):
         """Clean the cache if necessary
diff --git a/meld/matchers.py b/meld/matchers.py
index c2966a2..9f03ead 100644
--- a/meld/matchers.py
+++ b/meld/matchers.py
@@ -17,6 +17,25 @@
 
 from collections import namedtuple
 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):


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]