aboutsummaryrefslogtreecommitdiffstats
path: root/src/py/imc/async.py
blob: c0df3385b859ff2cb160077e236da86399b78749 (plain) (blame)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import traceback
import uuid
import ssl

import tornado.stack_context
from Crypto.Hash import SHA512
from greenlet import greenlet

from imc import auth

gr_idmap = {}
ret_idmap = {}
gr_main = greenlet.getcurrent()

def switch_top():
    global gr_main

    assert greenlet.getcurrent() != gr_main

    old_iden = auth.current_iden
    old_contexts = tornado.stack_context._state.contexts
    auth.current_iden = None

    result =  gr_main.switch(None)

    tornado.stack_context._state.contexts = old_contexts
    auth.current_iden = old_iden

    return result

def caller(f):
    def wrapper(*args,**kwargs):
        global gr_main
        global gr_idmap
        global ret_idmap

        def _call(*args,**kwargs):
            ret = f(*args,**kwargs)
            retids = gr_idmap[grid]
            for retid in retids:
                del ret_idmap[retid] 

            del gr_idmap[grid]

            return (True,ret)
        
        try:
            gr = greenlet(_call)
            grid = id(gr)
            gr_idmap[grid] = set()
            old_iden = auth.current_iden
            old_contexts = tornado.stack_context._state.contexts

            result = gr.switch(*args,**kwargs)

            tornado.stack_context._state.contexts = old_contexts
            auth.current_iden = old_iden

            if result == None:
                return (False,None)

            if gr.dead == False:
                gr.parent = gr_main

            return result

        except TypeError as err:
            traceback.print_stack()
            print(err)
            return (False,'Eparameter')

        except Exception as err:
            traceback.print_stack()
            print(err)
            return (False,'Einternal')

    return wrapper

def get_retid():
    global gr_idmap
    global ret_idmap

    gr = greenlet.getcurrent()
    grid = id(gr)
    retid = SHA512.new(uuid.uuid1().bytes + ssl.RAND_bytes(64)).hexdigest()

    gr_idmap[grid].add(retid)
    ret_idmap[retid] = gr

    return retid

def ret(retid,value = None,err = None):
    global gr_main
    global gr_idmap
    global ret_idmap

    assert greenlet.getcurrent() == gr_main

    try:
        gr = ret_idmap.pop(retid)
        gr_idmap[id(gr)].remove(retid)

    except KeyError:
        return

    try:
        old_iden = auth.current_iden
        old_contexts = tornado.stack_context._state.contexts

        if err == None:
            gr.switch(value)
        
        else:
            gr.throw(err)

        tornado.stack_context._state.contexts = old_contexts
        auth.current_iden = old_iden

    except TypeError as err:
        traceback.print_stack()
        print(err)