Source

asyncplot / asyncplot / server.py

Full commit
r"""Threaded Socket Server"""

import cPickle
#import socket
import threading
import SocketServer


class PlotRequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.request.sendall(self.server.get_data())


class PlotSocketServer(SocketServer.ThreadingMixIn,
                       SocketServer.TCPServerThread):
    r"""Simple threaded socket server.  Listens on the specified port, and
    launches Socket threads on connection.

    Call :meth:`update` to update the plot data.

    To Do
    -----
    * Add timeouts.
    """
    _PORT = 9999

    def __init__(self, host='', port=_PORT):
        self.lock = threading.Lock()  # RLock()??
        self.have_data = threading.Event()
        self.data = None
        super(PlotSocketServer, self).__init__((host, port),
                                               PlotRequestHandler)

    def get_data(self, block=True):
        r"""The object is pickled here."""
        self.have_data.wait()
        with self.lock:
            return cPickle.dumps(self.data)
        
    def update(self, *v, **kw):
        with self.lock:
            self.data = (v, kw)
        self.have_data.set()


class Server(threading.Thread):
    def __init__(self, host='', port=PlotSocketServer._PORT):
        self.server = PlotSocketServer(host=host, port=port)
        threading.Thread.__init__(self, target=self.server.serve_forever)
        self.daemon = True      # Don't keep python alive.

    def __enter__(self):
        self.start()
        return self.server

    def __exit__(self, type, value, traceback):
        self.server.shutdown()
        return value == None


def example_server():
    import numpy as np
    x = np.linspace(0, 2*np.pi, 100)
    t = 0
    dt = 0.01
    with Server() as s:
        for n in xrange(1000000):
            t += dt
            y = np.sin(x + t)
            s.update(x, y)