blob: 24ad9406c52801b4f64870175bef083cea7e5e51 [file] [log] [blame]
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import threading
from devil.utils import reraiser_thread
from devil.utils import timeout_retry
class WeakConstant(object):
"""A thread-safe, lazily initialized object.
This does not support modification after initialization. The intended
constant nature of the object is not enforced, though, hence the "weak".
"""
def __init__(self, initializer):
self._initialized = threading.Event()
self._initializer = initializer
self._lock = threading.Lock()
self._val = None
def read(self):
"""Get the object, creating it if necessary."""
if self._initialized.is_set():
return self._val
with self._lock:
if not self._initialized.is_set():
# We initialize the value on a separate thread to protect
# from holding self._lock indefinitely in the event that
# self._initializer hangs.
initializer_thread = reraiser_thread.ReraiserThread(
self._initializer)
initializer_thread.start()
timeout_retry.WaitFor(
lambda: initializer_thread.join(1) or not initializer_thread.isAlive(),
wait_period=0)
self._val = initializer_thread.GetReturnValue()
self._initialized.set()
return self._val