From 497fb9e21f45ec08e1486abaee6dfa7b20b8a691 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Wed, 24 Mar 2021 18:08:54 -0700 Subject: Initial revision --- smart_future.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 smart_future.py (limited to 'smart_future.py') diff --git a/smart_future.py b/smart_future.py new file mode 100644 index 0000000..f1ffee1 --- /dev/null +++ b/smart_future.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +from __future__ import annotations +from collections.abc import Mapping +import concurrent.futures as fut +import time +from typing import Callable, List, TypeVar + +from deferred_operand import DeferredOperand +import id_generator + +T = TypeVar('T') + + +def wait_many(futures: List[SmartFuture], *, callback: Callable = None): + finished: Mapping[int, bool] = {} + x = 0 + while True: + future = futures[x] + if not finished.get(future.get_id(), False): + if future.is_ready(): + finished[future.get_id()] = True + yield future + else: + if callback is not None: + callback() + time.sleep(0.1) + x += 1 + if x >= len(futures): + x = 0 + if len(finished) == len(futures): + if callback is not None: + callback() + return + + +class SmartFuture(DeferredOperand): + """This is a SmartFuture, a class that wraps a normal Future and can + then be used, mostly, like a normal (non-Future) identifier. + + Using a FutureWrapper in expressions will block and wait until + the result of the deferred operation is known. + """ + + def __init__(self, wrapped_future: fut.Future) -> None: + self.wrapped_future = wrapped_future + self.id = id_generator.get("smart_future_id") + + def get_id(self) -> int: + return self.id + + def is_ready(self) -> bool: + return self.wrapped_future.done() + + # You shouldn't have to call this; instead, have a look at defining a + # method on DeferredOperand base class. + def _resolve(self, *, timeout=None) -> T: + return self.wrapped_future.result(timeout) -- cgit v1.3