URI: 
       tIntroduce thread job framework. - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 56654ec4e984e14990813ab034ab2c6873558cea
   DIR parent 6682135a23e4688af7d618bbfbf157d4ae6f5042
  HTML Author: Neil Booth <kyuupichan@gmail.com>
       Date:   Wed, 26 Aug 2015 16:41:12 +0900
       
       Introduce thread job framework.
       
       This is a cleaner generalization of the functionality added
       tto network_proxy.py a few months ago, whereby jobs can be
       added and removed from a thread's main loop.  This allows
       us to cut down on unnecessary threads.
       
       A follow-up patch will update the proxy to this framework.
       
       Diffstat:
         M lib/util.py                         |      37 ++++++++++++++++++++++++++++++-
       
       1 file changed, 36 insertions(+), 1 deletion(-)
       ---
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -3,6 +3,7 @@ import platform
        import shutil
        from datetime import datetime
        from decimal import Decimal
       +import traceback
        import urlparse
        import urllib
        import threading
       t@@ -24,6 +25,20 @@ class MyEncoder(json.JSONEncoder):
                    return obj.as_dict()
                return super(MyEncoder, self).default(obj)
        
       +class ThreadJob:
       +    """A job that is run periodically from a thread's main loop.  run() is
       +    called from that thread's context.
       +    """
       +
       +    def print_error(self, *msg):
       +        print_error("[%s]" % self.__class__.__name__, *msg)
       +
       +    def print_msg(self, *msg):
       +        print_msg("[%s]" % self.__class__.__name__, *msg)
       +
       +    def run(self):
       +        """Called periodically from the thread"""
       +        pass
        
        class DaemonThread(threading.Thread):
            """ daemon thread that terminates cleanly """
       t@@ -33,6 +48,27 @@ class DaemonThread(threading.Thread):
                self.parent_thread = threading.currentThread()
                self.running = False
                self.running_lock = threading.Lock()
       +        self.job_lock = threading.Lock()
       +        self.jobs = []
       +
       +    def add_job(self, job):
       +        with self.job_lock:
       +            self.jobs.append(job)
       +
       +    def run_jobs(self):
       +        # Don't let a throwing job disrupt the thread, future runs of
       +        # itself, or other jobs.  This is useful protection against
       +        # malformed or malicious server responses
       +        with self.job_lock:
       +            for job in self.jobs:
       +                try:
       +                    job.run()
       +                except:
       +                    traceback.print_exc(file=sys.stderr)
       +
       +    def remove_job(self, job):
       +        with self.job_lock:
       +            self.jobs.remove(job)
        
            def start(self):
                with self.running_lock:
       t@@ -337,7 +373,6 @@ import socket
        import errno
        import json
        import ssl
       -import traceback
        import time
        
        class SocketPipe: