Introduce thread job framework.

This is a cleaner generalization of the functionality added
to 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.
This commit is contained in:
Neil Booth 2015-08-26 16:41:12 +09:00
parent 6682135a23
commit 56654ec4e9
1 changed files with 36 additions and 1 deletions

View File

@ -3,6 +3,7 @@ import platform
import shutil
from datetime import datetime
from decimal import Decimal
import traceback
import urlparse
import urllib
import threading
@ -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 """
@ -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:
@ -337,7 +373,6 @@ import socket
import errno
import json
import ssl
import traceback
import time
class SocketPipe: