#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
线程future
如果某些函数耗时较长，且不提供异步回调的功能，例如同步调用mysql，执行一个耗时ssh命令并返回结果，
这些函数无法正常利用tornado的async特性，此处利用线程池模拟了一个异步方法，可以防止同步耗时操作阻塞进程，
只要在需要异步的方法上加上@thread_future装饰，并且函数最后一个参数为callback函数，则该函数便可以支持
@asynchronous或gen.Task的非阻塞方式调用

依赖：该方法必须安装futures模块才可以使用
例子：
@async_execute
def dosomething(a,b,callback):
    # 这里可能耗时很久
    #callback参数不会在这里有任何调用，这个耗时方法并没有异步功能
    #该装饰器为此方法模拟了异步操作，但注意：这是用线程模拟的！！
    # something...
    result='return'
    return result

class Index(handler):
    @asynchronous
    def get(self):
        a=''
        b=''
        dosomething(self.callback)

    def callback(self,result):
        self.finish(result)

"""

import functools
from tornado.netutil import Resolver, ThreadedResolver
from tornado.ioloop import IOLoop

Resolver.configure('tornado.netutil.ThreadedResolver',
                   num_threads=10)

from torngas.exception import ArgumentError


def async_execute(method):
    @functools.wraps(method)
    def decor(*args, **kwargs):
        def wrapper(callback):
            thread_resolver = ThreadedResolver()
            fut = thread_resolver.executor.submit(method, *args, **kwargs)
            fut.add_done_callback(
                lambda future: IOLoop.current().add_callback(functools.partial(callback, future.result())))

        callback = kwargs.get('callback', None)

        if not callback:
            callback = args[-1]
        if not callable(callback):
            raise ArgumentError("The last parameter named 'callback' must be a callable function.")

        return wrapper(callback)

    return decor


if __name__ == '__main__':
    pass

@@ -385,15 +385,44 @@
 %E8%80%97%E6%97%B6%E6%96%B9%E6%B3%95
+%E6%9C%AC%E8%BA%AB
 %E5%B9%B6%E6%B2%A1%E6%9C%89%E5%BC%82%E6%AD%A5
-%E5%8A%9F%E8%83%BD
+%EF%BC%8C%0A    #%E5%90%8C%E6%AD%A5%E7%9A%84%E6%96%B9%E6%B3%95%E6%97%A0%E8%AE%BA%E5%A6%82%E4%BD%95%E9%83%BD%E4%B8%8D%E4%BC%9A%E6%AF%AB%E6%97%A0%E4%BB%A3%E4%BB%B7%E7%9A%84%E5%8F%98%E6%88%90%E5%BC%82%E6%AD%A5%EF%BC%8C
 %0A   
@@ -429,18 +429,16 @@
  #%E8%AF%A5%E8%A3%85%E9%A5%B0%E5%99%A8%E4%B8%BA%E6%AD%A4
-%E6%96%B9%E6%B3%95
 %E6%A8%A1%E6%8B%9F%E4%BA%86%E5%BC%82%E6%AD%A5%E6%93%8D%E4%BD%9C%EF%BC%8C
@@ -450,13 +450,12 @@
 %E6%98%AF%E7%94%A8%E7%BA%BF%E7%A8%8B
+%E6%B1%A0
 %E6%A8%A1%E6%8B%9F%E7%9A%84
-%EF%BC%81%EF%BC%81
 %0A   

Update async_execute.py