2012-10-11 85 views
11

一種方式來獲得一個std::future通過std::async如何分配與std :: future相關的存儲?

int foo() 
{ 
    return 42; 
} 

... 

std::future<int> x = std::async(foo); 

在這個例子中,是如何分配給x的異步狀態的存儲,以及線程(如果有多個線程參與)負責執行分配?此外,std::async的客戶是否對分配有任何控制權?

對於背景下,我看到的std::promiseone of the constructors可能會收到一個allocator,但如果它是可以定製在std::async水平std::future的分配目前還不清楚我。

回答

5

僅僅從std::async的簡單論據來看,似乎沒有辦法控制內部std::promise的分配,因此它可以只使用任何東西,儘管可能是std::allocator。雖然我在理論上猜想它沒有指定,但共享狀態很可能是在調用線程內分配的。我沒有在標準中找到有關此事的明確信息。最後std::async是一個非常容易異步調用的專用工具,因此您不必考慮是否存在任何地方實際上 a std::promise

爲了更直接地控制異步調用的行爲,還有std::packaged_task,它確實有一個分配器參數。但是從純粹的標準報價來看,這個分配器是否僅僅用於爲函數分配存儲空間並不十分清楚(因爲std::packaged_task是一種特殊的std::function),或者它也用於分配內部的共享狀態std::promise似乎有可能:

30.6.9.1 [futures.task.members]:

影響:構造了一個新的packaged_task對象與共享狀態和 初始化對象與std::forward<F>(f)存儲任務。採用Allocator參數的 構造函數使用它來分配存儲內部數據結構所需的內存 。

好了,它甚至不說有一個std::promise下(同樣爲std::async),它可能只是一個未定義的類型連接到std::future

因此,如果確實沒有指定如何分配其內部共享狀態,最好的辦法可能是實現自己的設施進行異步函數調用。考慮到,簡單地說,std::packaged_task只是一個std::functionstd::promisestd::async捆綁在一個新的線程(當然,除非沒有),只是開始std::packaged_task,這應該不是太多的問題。

但實際上這可能是規範中的疏忽。雖然分配控制並不適合std::async,但std::packaged_task的解釋及其對分配器的使用可能會更清楚一些。但這也可能是故意的,所以std::packaged_task可以隨意使用,甚至不需要在內部使用std::promise

編輯:重讀它,我覺得上面的標準報價確實說,該std::packaged_task的共享狀態使用提供的分配程序分配,因爲它是‘內部數據結構’的一部分,不管這些是什麼(雖然不需要是實際的std::promise)。所以我認爲std::packaged_task應該足夠顯式控制異步任務的共享狀態std::future

5

內存由調用std::async的線程分配的,你必須在它是如何做任何控制。通常情況下,它將通過new __internal_state_type的一些變體完成,但沒有保證;它可以使用malloc,或專門爲此目的選擇的分配器。

從30.6.8p3 [futures.async]:

「效果:第一個函數的行爲相同於第二函數調用與launch::async | launch::deferred的策略參數,並用於FArgs相同的參數。第二個函數創建與返回的未來對象關聯的共享狀態...「

」第一個功能「是沒有啓動策略的過載,而第二個功能是帶啓動策略的超載。

std::launch::deferred的情況下,沒有其他線程,所以一切都必須發生在調用線程上。在std::launch::async的情況下,30.6.8p3接着說:

- 如果policy & launch::async非零 - 調用INVOKE (DECAY_COPY (std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...)(20.8.2,30.3.1.2),就好像在一個新的執行線程通過一個代表線程對象,在調用async的線程中對DECAY_COPY()的調用進行評估。 ...

我已經添加了重點。由於函數和參數的副本必須在調用線程中發生,這基本上要求共享狀態由調用線程分配。

當然,你可以編寫一個啓動新線程的實現,等待它分配狀態,然後返回一個引用它的future,但爲什麼你會這樣?

+0

它在哪裏保證調用線程分配存儲?好的,這很可能,但我仍然希望看到標準的報價。 –

+0

更新的答案更詳細。 –

+0

確實,這似乎很清楚,我忽略了這一點。但是,像你現在這樣在你的回答中指出這一點不能造成任何傷害。感謝和+1。 –