成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

從 async_call_method() 開始探索

light / 1407人閱讀

摘要:定義一個閉包相關官方文檔是一種用于并發(fā)編程的模式,首次引入是在的模塊。對象是一個對于異步返回結果的占位符。一個對象包含了一次異步操作的結果。在同步編程中,被用于等待從一個線程池或進程池里返回的結果在中,通常被用在或者在一個函數(shù)中它們。

from tornado.concurrent import Future

def async_call_method(fun, *args, **kwargs):
    future = Future()
    // 定義一個閉包 finish
    def finish():
        try:
            result = fun(*args, **kwargs)
            if future._callbacks:
                IOLoop.current().add_callback(future.set_result, result)
            else:
                future.set_result(result)
        except:
            if future._callbacks:
                IOLoop.current().add_callback(future.set_exc_info, sys.exc_info())
            else:
                future.set_exc_info(sys.exc_info())
    child_gr = greenlet.greenlet(finish)
    child_gr.switch()
    return future
tornado 相關官方文檔

Future 是一種用于并發(fā)編程的模式,首次引入是在 python 3.2 的 concurrent.futures 模塊。

Future 對象是一個對于異步返回結果的占位符。

一個 Future 對象包含了一次異步操作的結果。在同步編程中,F(xiàn)utures 被用于等待從一個線程池或進程池里返回的結果;在 tornado 中,future 通常被用在 IOLoop.add_future 或者在一個 gen.coroutine 函數(shù)中 yielding 它們。

tornado.concurrent.Future 和 concurrent.futures.Future 相似,但是其不是線程安全的(因此,在單線程事件循環(huán)應用在速度更快)

async_call_method() 的來源

經(jīng)過一番搜索,查詢到 async_call_method() 這個函數(shù)來自于 github.com/snower/TorMySQL.

經(jīng)過對該項目代碼的仔細閱讀,我發(fā)現(xiàn)了它是如何實現(xiàn)了 mysql 的異步操作。

tormysql.client.connect()
...
def connect(self):
    # 入口函數(shù)
    # 設置 future 占位符
    future = Future()

    # 定義回調(diào)函數(shù)
    def on_connected(connection_future):
        if connection_future._exc_info is None:
            future.set_result(self)
        else:
            future.set_exc_info(connection_future.exc_info())
    self._connection = Connection(defer_connect = True, *self._args, **self._kwargs)
    self._connection.set_close_callback(self.connection_close_callback)

    # 用 greenlet 包裝 self._connection.connect 并返回 future
    # 要使 async_call_method 包裝后的函數(shù)有非阻塞的特性,必須達成以下要求
    # 1. 函數(shù)可以訪問 父greenlet
    # 2. 函數(shù)中所有 IO 操作均支持非阻塞(比如: 非阻塞由 socket 的 non-blocking 特性支持)
    # 3. 函數(shù)中執(zhí)行 IO 操作后立即將運行權交還給主函數(shù)(父greenlet, 如:ioloop 時間循環(huán))(greenlet.switch)
    # 4. 函數(shù)中所有 IO 操作均返回 Future
    # 5. Future.callback 運行后立即將運行權(greenlet.switch)返回給當前函數(shù)(greenlet.current),完成當前函數(shù)的剩余部分
    connection_future = async_call_method(self._connection.connect)

    # 當 connection_future 狀態(tài)為 finished, 調(diào)用 on_connected()
    # finished => 調(diào)用 connection_future.set_result()
    IOLoop.current().add_future(connection_future, on_connected)
    return future
...
self._connection.connect()
...
        # IOStream 基于 tornado.iostream.IOStream
        sock = IOStream(sock)
        sock.set_close_callback(self.stream_close_callback)

        # getcurrent() 返回包裝了當前函數(shù)的 greenlet
        child_gr = greenlet.getcurrent()
        # main 是指 父greenlet(主函數(shù), 時間循環(huán)?)
        main = child_gr.parent
        assert main is not None, "Execut must be running in child greenlet"
...
    def connected(future):
        if self._loop_connect_timeout:
            self._loop.remove_timeout(self._loop_connect_timeout)
            self._loop_connect_timeout = None
    
        if future._exc_info is not None:
            child_gr.throw(future.exception())
        else:
            self._sock = sock
            # 將運行權交還給當前 greenlet
            child_gr.switch()
    
    # IOStream.connect 是 no-blocking 的 socket 操作
    future = sock.connect(address)
    # 給 sock.connect 操作添加回調(diào)函數(shù)
    self._loop.add_future(future, connected)
    # 然后把運行權交還給 父greenlet
    # 直到連接成功,connected() 中會將運行權交還給 當前greenlet
    main.switch()
...
結論

要使 async_call_method 包裝后的函數(shù)有非阻塞的特性,必須達成以下要求

函數(shù)可以訪問 父greenlet

函數(shù)中所有 IO 操作均支持非阻塞(比如: 非阻塞由 socket 的 non-blocking 特性支持)

函數(shù)中執(zhí)行 IO 操作后立即將運行權交還給主函數(shù)(父greenlet, 如:ioloop 時間循環(huán))(greenlet.switch)

函數(shù)中所有 IO 操作均返回 Future

Future.callback 運行后立即將運行權(greenlet.switch)返回給當前函數(shù)(greenlet.current),完成當前函數(shù)的剩余部分

async_call_method 包裝后的函數(shù)要實現(xiàn)非阻塞,最終還是依賴于 socket 的非阻塞
=> socket.setblocking(False)

github.com/snower/TorMySQL 中于 mysql 的交互全部通過 IOStream() 的以下方法實現(xiàn):

* def _handle_events(self, fd, events):  # ioloop 在事件發(fā)生時調(diào)用 _handle_events
* def _handle_connect(self): 
* def _handle_read(self):  # 當事件為讀取事件時,讀取數(shù)據(jù)到 buffer, 然后 future.set_result(data)
* def _handle_write(self):  # 當事件為寫事件時,讀取數(shù)據(jù)到 buffer, 然后 future.set_result(data)
* def read(self, num_bytes):
* def write(self, data):

通過對上述方法進行 設置 future 占位符,并基于 non-blocking socket 實現(xiàn)上述方法的非阻塞。

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/40725.html

相關文章

  • 基于Tableau探索分析世界銀行提供的關于科學技術的數(shù)據(jù)

    摘要:并且在年中國第一次在專利總量超過美國,躍升至第一位,成為提交國際專利申請量最多的國家,從而打破了美國長達年的專利申請霸主地位。中國的技術創(chuàng)新仍處于大部分技術靠從外國購買技術專利的階段。 要求 ????????????????對 CSE512: Data Visualization 完成探索性...

    alighters 評論0 收藏0
  • [譯] 解密 Uber 數(shù)據(jù)部門的數(shù)據(jù)可視化最佳實踐

    摘要:讓我們看看都做了哪些工作可視化分析增強數(shù)據(jù)可操作性測試平臺的表格和置信區(qū)間可視化可視化分析主要都是由抽象數(shù)據(jù)可視化組成的。大多數(shù)有效的可視化分析在這種情況下都是關于報告儀表盤實時分析的圖標和網(wǎng)絡圖。 showImg(https://segmentfault.com/img/remote/1460000006771644); 概述 在2015年初,我們在Uber規(guī)劃了一個官方的數(shù)據(jù)科學團...

    darkbug 評論0 收藏0
  • [譯] 解密 Uber 數(shù)據(jù)部門的數(shù)據(jù)可視化最佳實踐

    摘要:讓我們看看都做了哪些工作可視化分析增強數(shù)據(jù)可操作性測試平臺的表格和置信區(qū)間可視化可視化分析主要都是由抽象數(shù)據(jù)可視化組成的。大多數(shù)有效的可視化分析在這種情況下都是關于報告儀表盤實時分析的圖標和網(wǎng)絡圖。 showImg(https://segmentfault.com/img/remote/1460000006771644); 概述 在2015年初,我們在Uber規(guī)劃了一個官方的數(shù)據(jù)科學團...

    susheng 評論0 收藏0
  • 簡潔明了探索瀏覽器Event loop

    摘要:前段時間我對于瀏覽器中的和哪個先執(zhí)行有所困惑,苦于搜索也沒有發(fā)現(xiàn)很明確的答案,于是決定深入探索瀏覽器,現(xiàn)有所愚見,想與大家分享,希望能幫助到那些還在爬坑的人。瀏覽器端中的異步隊列有兩種隊列和隊列。瀏覽器會不斷從隊列中按順序取執(zhí)行。 前段時間我對于瀏覽器Event loop中的MacroTask和MicroTask哪個先執(zhí)行有所困惑,苦于搜索也沒有發(fā)現(xiàn)很明確的答案,于是決定深入探索瀏覽器...

    DrizzleX 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<