1# Copyright 2015 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 5import threading 6 7from devil.utils import reraiser_thread 8from devil.utils import timeout_retry 9 10 11class WeakConstant(object): 12 """A thread-safe, lazily initialized object. 13 14 This does not support modification after initialization. The intended 15 constant nature of the object is not enforced, though, hence the "weak". 16 """ 17 18 def __init__(self, initializer): 19 self._initialized = threading.Event() 20 self._initializer = initializer 21 self._lock = threading.Lock() 22 self._val = None 23 24 def read(self): 25 """Get the object, creating it if necessary.""" 26 if self._initialized.is_set(): 27 return self._val 28 with self._lock: 29 if not self._initialized.is_set(): 30 # We initialize the value on a separate thread to protect 31 # from holding self._lock indefinitely in the event that 32 # self._initializer hangs. 33 initializer_thread = reraiser_thread.ReraiserThread( 34 self._initializer) 35 initializer_thread.start() 36 timeout_retry.WaitFor( 37 lambda: initializer_thread.join(1) or not initializer_thread.isAlive(), 38 wait_period=0) 39 self._val = initializer_thread.GetReturnValue() 40 self._initialized.set() 41 42 return self._val 43