Source code for horizon.utils.threaded
# Copyright 2016 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import sys
from threading import Thread
[docs]class ThreadedPromise(Thread):
def __init__(self, target=None, args=(), kwargs=None, **_kwargs):
if kwargs is None:
kwargs = {}
super(ThreadedPromise, self).__init__(target=target, args=args,
kwargs=kwargs, **_kwargs)
self.__target = target
self.__args = args
self.__kwargs = kwargs
self.__result = None
self.__exc_info = None
[docs] def run(self):
try:
if self.__target:
self.__result = self.__target(*self.__args, **self.__kwargs)
except Exception:
self.__exc_info = sys.exc_info()
finally:
# Avoid a refcycle if the thread is running a function with
# an argument that has a member that points to the thread.
del self.__target, self.__args, self.__kwargs
@property
def result(self):
self.propagate_exceptions()
return self.__result
[docs] def propagate_exceptions(self):
self.join()
if self.__exc_info is not None:
raise self.__exc_info[0], self.__exc_info[1], self.__exc_info[2]
[docs]def promise(func):
def wrapped(*args, **kwargs):
th_promise = ThreadedPromise(target=func, args=args, kwargs=kwargs)
th_promise.start()
return th_promise
return wrapped