Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Rpyc/AsyncNetProxy.py
blob: 06b230a3b35c388ed8ad91e864a3a33857feeb87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from NetProxy import NetProxyWrapper, _get_conn, _get_oid
from Lib import raise_exception


class AsyncNetProxy(NetProxyWrapper):
    """wraps an exiting synchronous netproxy to make is asynchronous 
    (remote operations return AsyncResult objects)"""
    __slots__ = []

    def __request__(self, handler, *args):
        res = AsyncResult(_get_conn(self))
        _get_conn(self).async_request(res.callback, handler, _get_oid(self), *args)
        return res

    # must return a string... and it's not meaningful to return the repr of an async result
    def __repr__(self, *args):
        return self.__request__("handle_repr", *args).result
    def __str__(self, *args):
        return self.__request__("handle_str", *args).result      


class AsyncResult(object):
    """represents the result of an asynchronous operation"""
    STATE_PENDING = "pending"
    STATE_READY = "ready"
    STATE_EXCEPTION = "exception"
    __slots__ = ["conn", "_state", "_result", "_on_ready"]
    
    def __init__(self, conn):
        self.conn = conn
        self._state = self.STATE_PENDING
        self._result = None
        self._on_ready = None
    
    def __repr__(self):
        return "<AsyncResult (%s) at 0x%08x>" % (self._state, id(self))
    
    def callback(self, obj, is_exception):
        self._result = obj
        if is_exception:
            self._state = self.STATE_EXCEPTION
        else:
            self._state = self.STATE_READY
        if self._on_ready is not None:
            self._on_ready(self)
    
    def _get_on_ready(self):
        return self._ready_callback

    def _set_on_ready(self, obj):
        self._on_ready = obj
        if self._state != self.STATE_PENDING:
            self._on_ready(self)
    
    def _get_is_ready(self):
        if self._state == self.STATE_PENDING:
            self.conn.poll()
        return self._state != self.STATE_PENDING
    
    def _get_result(self):
        while self._state == self.STATE_PENDING:
            self.conn.serve()
        if self._state == self.STATE_READY:
            return self._result
        elif self._state == self.STATE_EXCEPTION:
            raise_exception(*self._result)
    
    is_ready = property(_get_is_ready, 
        doc = "indicates whether or not the result is ready")
    result = property(_get_result, 
        doc = "the value of the async result (may block)")
    on_ready = property(_get_on_ready, _set_on_ready, 
        doc = "if not None, specifies a callback which is called when the result is ready")