Source

asyncplot / asyncplot / server.py

r"""Threaded Socket Server"""

import cPickle
import socket
import threading
import SocketServer

import mmf


class PlotRequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.request.sendall(self.server.get_data())
        #self.request.shutdown(socket.SHUT_RDWR)
        #self.request.close()


class PlotSocketServer(SocketServer.ThreadingMixIn,
                       SocketServer.TCPServer):
    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
    _HOST = ''

    def __init__(self, host=_HOST, port=_PORT):
        self.lock = threading.Lock()  # RLock()??
        self.have_data = threading.Event()
        self.data = None
        
        self.daemon_threads = True       # Don't keep python alive.
        self.allow_reuse_address = True  # Allow port reuse after termination.
        SocketServer.TCPServer.__init__(self, (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()    # This is very slow!


class Server(threading.Thread):
    def __init__(self, host=PlotSocketServer._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):
        #mmf.mdb()
        self.start()
        return self.server

    def __exit__(self, type, value, traceback):
        #mmf.mdb()
        self.server.shutdown()
        return value is None


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