#ckwg +4
# Copyright 2012 by Kitware, Inc. All Rights Reserved. Please refer to
# KITWARE_LICENSE.TXT for licensing information, or contact General Counsel,
# Kitware, Inc., 28 Corporate Drive, Clifton Park, NY 12065.


from vistk.pipeline import config
from vistk.pipeline import datum
from vistk.pipeline import edge
from vistk.pipeline import pipeline
from vistk.pipeline import process
from vistk.pipeline import scheduler
from vistk.pipeline import utils

import threading


class UnsupportedProcess(Exception):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        fmt = "The process '%s' does not support running in a Python thread"
        return (fmt % self.name)


class PyThreadPerProcessScheduler(scheduler.PythonScheduler):
    """ Runs each process in a pipeline in its own thread.
    """

    def __init__(self, pipe, conf):
        scheduler.PythonScheduler.__init__(self, pipe, conf)

        p = self.pipeline()
        names = p.process_names()

        no_threads = process.PythonProcess.constraint_no_threads

        for name in names:
            proc = p.process_by_name(name)
            constraints = proc.constraints()

            if no_threads in constraints:
                raise UnsupportedProcess(name)

        self._threads = []
        self._event = threading.Event()
        self._make_monitor_edge_config()

    def _start(self):
        p = self.pipeline()
        names = p.process_names()

        for name in names:
            proc = p.process_by_name(name)

            thread = threading.Thread(target=self._run_process, name=name, args=(proc,))

            self._threads.append(thread)

        for thread in self._threads:
            thread.start()

    def _wait(self):
        for thread in self._threads:
            thread.join()

    def _stop(self):
        self._event.set()

    def _run_process(self, proc):
        utils.name_thread(proc.name())

        monitor = edge.Edge(self._edge_conf)

        proc.connect_output_port(process.PythonProcess.port_heartbeat, monitor)

        complete = False

        while not complete and not self._event.is_set():
            proc.step()

            while monitor.has_data():
                edat = monitor.get_datum()
                dat = edat.datum

                if dat.type() == datum.DatumType.complete:
                    complete = True

    def _make_monitor_edge_config(self):
        self._edge_conf = config.empty_config()

@@ -1291,16 +1291,62 @@
 ds = %5B%5D%0A
+        self._pause_event = threading.Event()%0A
         
@@ -1369,32 +1369,32 @@
 reading.Event()%0A
-
         self._ma
@@ -1853,24 +1853,137 @@
 ead.join()%0A%0A
+    def _pause(self):%0A        self._pause_event.set()%0A%0A    def _resume(self):%0A        self._pause_event.clear()%0A%0A
     def _sto
@@ -2245,16 +2245,16 @@
  False%0A%0A
-
         
@@ -2298,24 +2298,112 @@
 t.is_set():%0A
+            while self._pause_event.is_set():%0A                self._pause_event.wait()%0A%0A
             

Implement pause/resume in pythread_per_process