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