OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
| 5 import logging |
5 import sys | 6 import sys |
| 7 import traceback |
6 | 8 |
7 _no_value = object() | 9 _no_value = object() |
8 | 10 |
9 | 11 |
10 def _DefaultErrorHandler(error): | 12 def _DefaultErrorHandler(error): |
11 raise error | 13 raise error |
12 | 14 |
13 | 15 |
14 def All(futures, except_pass=None): | 16 def All(futures, except_pass=None, except_pass_log=False): |
15 '''Creates a Future which returns a list of results from each Future in | 17 '''Creates a Future which returns a list of results from each Future in |
16 |futures|. | 18 |futures|. |
17 | 19 |
18 If any Future raises an error other than those in |except_pass| the returned | 20 If any Future raises an error other than those in |except_pass| the returned |
19 Future will raise as well. | 21 Future will raise as well. |
| 22 |
| 23 If any Future raises an error in |except_pass| then None will be inserted as |
| 24 its result. If |except_pass_log| is True then the exception will be logged. |
20 ''' | 25 ''' |
21 def resolve(): | 26 def resolve(): |
22 resolved = [] | 27 resolved = [] |
23 for f in futures: | 28 for f in futures: |
24 try: | 29 try: |
25 resolved.append(f.Get()) | 30 resolved.append(f.Get()) |
26 # "except None" will simply not catch any errors. | 31 # "except None" will simply not catch any errors. |
27 except except_pass: | 32 except except_pass: |
| 33 if except_pass_log: |
| 34 logging.error(traceback.format_exc()) |
| 35 resolved.append(None) |
28 pass | 36 pass |
29 return resolved | 37 return resolved |
30 return Future(callback=resolve) | 38 return Future(callback=resolve) |
31 | 39 |
32 | 40 |
33 def Race(futures, except_pass=None): | 41 def Race(futures, except_pass=None, default=_no_value): |
34 '''Returns a Future which resolves to the first Future in |futures| that | 42 '''Returns a Future which resolves to the first Future in |futures| that |
35 either succeeds or throws an error apart from those in |except_pass|. | 43 either succeeds or throws an error apart from those in |except_pass|. |
36 | 44 |
37 If all Futures throw errors in |except_pass| then the returned Future | 45 If all Futures throw errors in |except_pass| then |default| is returned, |
38 will re-throw one of those errors, for a nice stack trace. | 46 if specified. If |default| is not specified then one of the passed errors |
| 47 will be re-thrown, for a nice stack trace. |
39 ''' | 48 ''' |
40 def resolve(): | 49 def resolve(): |
41 first_future = None | 50 first_future = None |
42 for future in futures: | 51 for future in futures: |
43 if first_future is None: | 52 if first_future is None: |
44 first_future = future | 53 first_future = future |
45 try: | 54 try: |
46 return future.Get() | 55 return future.Get() |
47 # "except None" will simply not catch any errors. | 56 # "except None" will simply not catch any errors. |
48 except except_pass: | 57 except except_pass: |
49 pass | 58 pass |
50 # Everything failed, propagate the first error even though it was | 59 if default is not _no_value: |
51 # caught by |except_pass|. | 60 return default |
| 61 # Everything failed and there is no default value, propagate the first |
| 62 # error even though it was caught by |except_pass|. |
52 return first_future.Get() | 63 return first_future.Get() |
53 return Future(callback=resolve) | 64 return Future(callback=resolve) |
54 | 65 |
55 | 66 |
56 class Future(object): | 67 class Future(object): |
57 '''Stores a value, error, or callback to be used later. | 68 '''Stores a value, error, or callback to be used later. |
58 ''' | 69 ''' |
59 def __init__(self, value=_no_value, callback=None, exc_info=None): | 70 def __init__(self, value=_no_value, callback=None, exc_info=None): |
60 self._value = value | 71 self._value = value |
61 self._callback = callback | 72 self._callback = callback |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 try: | 124 try: |
114 self._value = self._callback() | 125 self._value = self._callback() |
115 return self._value | 126 return self._value |
116 except: | 127 except: |
117 self._exc_info = sys.exc_info() | 128 self._exc_info = sys.exc_info() |
118 self._Raise() | 129 self._Raise() |
119 | 130 |
120 def _Raise(self): | 131 def _Raise(self): |
121 exc_info = self._exc_info | 132 exc_info = self._exc_info |
122 raise exc_info[0], exc_info[1], exc_info[2] | 133 raise exc_info[0], exc_info[1], exc_info[2] |
OLD | NEW |