OLD | NEW |
(Empty) | |
| 1 # Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 import logging |
| 6 import subprocess |
| 7 import threading |
| 8 |
| 9 |
| 10 class MotophoThread(threading.Thread): |
| 11 """Handles the running of the Motopho script and extracting results.""" |
| 12 def __init__(self, num_samples): |
| 13 threading.Thread.__init__(self) |
| 14 self._num_samples = num_samples |
| 15 self._latencies = [] |
| 16 self._correlations = [] |
| 17 # Threads can't be restarted, so in order to gather multiple samples, we |
| 18 # need to either re-create the thread for every iteration or use a loop |
| 19 # and locks in a single thread -> use the latter solution |
| 20 self._start_lock = threading.Event() |
| 21 self._finish_lock = threading.Event() |
| 22 self.BlockNextIteration() |
| 23 |
| 24 def run(self): |
| 25 for _ in xrange(self._num_samples): |
| 26 self._WaitForIterationStart() |
| 27 self._ResetEndLock() |
| 28 motopho_output = "" |
| 29 try: |
| 30 motopho_output = subprocess.check_output(["./motophopro_nograph"], |
| 31 stderr=subprocess.STDOUT) |
| 32 except subprocess.CalledProcessError as e: |
| 33 logging.error('Failed to run Motopho script: %s', e.output) |
| 34 raise e |
| 35 |
| 36 if "FAIL" in motopho_output: |
| 37 logging.error('Failed to get latency, logging raw output: %s', |
| 38 motopho_output) |
| 39 raise RuntimeError('Failed to get latency - correlation likely too low') |
| 40 |
| 41 current_num_samples = len(self._latencies) |
| 42 for line in motopho_output.split("\n"): |
| 43 if 'Motion-to-photon latency:' in line: |
| 44 self._latencies.append(float(line.split(" ")[-2])) |
| 45 if 'Max correlation is' in line: |
| 46 self._correlations.append(float(line.split(' ')[-1])) |
| 47 if (len(self._latencies) > current_num_samples and |
| 48 len(self._correlations) > current_num_samples): |
| 49 break; |
| 50 self._EndIteration() |
| 51 |
| 52 def _WaitForIterationStart(self): |
| 53 self._start_lock.wait() |
| 54 |
| 55 def StartIteration(self): |
| 56 """Tells the thread to start its next test iteration.""" |
| 57 self._start_lock.set() |
| 58 |
| 59 def BlockNextIteration(self): |
| 60 """Blocks the thread from starting the next iteration without a signal.""" |
| 61 self._start_lock.clear() |
| 62 |
| 63 def _EndIteration(self): |
| 64 self._finish_lock.set() |
| 65 |
| 66 def _ResetEndLock(self): |
| 67 self._finish_lock.clear() |
| 68 |
| 69 def WaitForIterationEnd(self, timeout): |
| 70 """Waits until the thread says it's finished or times out. |
| 71 |
| 72 Returns: |
| 73 Whether the iteration ended within the given timeout |
| 74 """ |
| 75 return self._finish_lock.wait(timeout) |
| 76 |
| 77 @property |
| 78 def latencies(self): |
| 79 return self._latencies |
| 80 |
| 81 @property |
| 82 def correlations(self): |
| 83 return self._correlations |
OLD | NEW |