作者Lipraxde (靜夜)
看板C_and_CPP
標題[問題] 關於 llvm 的 ThreadSafeModule 的疑惑
時間Sat Apr 13 16:16:30 2019
最近在用 llvm 的 OrcJIT,要將 Module 丟進去跑之前要轉成一個叫
ThreadSafeModule 的東東,再用 llvm::orc::IRLayer add 進去
ThreadSafeModule 大概長這樣:
class ThreadSafeModule {
public:
ThreadSafeModule() =
default;
ThreadSafeModule(ThreadSafeModule &&Other) =
default;
ThreadSafeModule &
operator=(ThreadSafeModule &&Other);
ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
: M(std::move(M)), TSCtx(std::move(Ctx)) {}
ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
: M(std::move(M)), TSCtx(std::move(TSCtx)) {}
Module *getModule() {
return M.get(); }
const Module *getModule()
const {
return M.get(); }
ThreadSafeContext::Lock getContextLock() {
return TSCtx.getLock(); }
explicit operator bool();
private:
std::unique_ptr<Module> M;
ThreadSafeContext TSCtx;
};
OrcJIT 跑完後如果中間有設 setNotifyCompiled 就會把 ThreadSafeModule 丟回來
然後 Module 就變成 ThreadSafeModule
把 ThreadSafeModule 釋放掉連帶著 Module 也釋放掉了
問題(Question):
1. 這個 ThreadSafeModule 為什麼要弄得像黑洞一樣?不把 Module release 出來
2. 它的 member function 'getModule',為什麼要寫一個有 const 一個沒有兩個版本?
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.113.210.55
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_and_CPP/M.1555143401.A.118.html
1F:→ loveme00835: 你就要看呼叫 getContextLock() 的地方了, 他比較像 04/14 00:46
2F:→ loveme00835: "Module with a mutex" 的概念, 不過他都 move 給你 04/14 00:47
3F:→ loveme00835: 註冊的 NotifyCompiledFunction, 等於生殺大權都交給 04/14 00:50
4F:→ loveme00835: 你, 其實就等於已經 release. 第 2 個是語言的問題 04/14 00:50
5F:→ loveme00835: , 為了傳遞和 this 相同的 const 語意, 簡單說如果透 04/14 00:54
6F:→ loveme00835: 過 const ThreadSafeModule& 拿到的 Module 物件也必 04/14 00:54
7F:→ loveme00835: 須是 const 的理由是: const T& 在你 statement 結束 04/14 00:56
8F:→ loveme00835: 前保證的語意是 "物件一直都存在", 所以當 this 給你 04/14 00:57
9F:→ loveme00835: 保證但回傳的 Module 不保證是很奇怪的 (因為 owning 04/14 00:57
10F:→ loveme00835: 語意), 另一方面 this 不保證但 Module 保證也很奇怪 04/14 00:58
11F:→ loveme00835: 這表示即使它給你 Module, 它還是可以偷偷把 Module 04/14 00:59
12F:→ loveme00835: 給 delete 掉 04/14 00:59
謝謝回覆,問題1的話生殺大權是拿回來了,不過變成另一種東西...有一種被強迫的感覺
問題2呢,想一想的確從 const 物件拿出來的東西,既然交給它管了那也該是 const。不
過「const T& 在你 statement 結束前保證的語意是 "物件一直都存在"」有點難懂,是
說 reference 到一個 const T,這個 reference 一直都有效的意思?
※ 編輯: Lipraxde (140.113.56.71), 04/14/2019 11:48:26
13F:→ loveme00835: 是啦, 不過既然你能把它的資源 move 到別邊就不是什 04/14 16:21
14F:→ loveme00835: 麼大問題. 問題 2 涉及的不只是 constness 的語意, 04/14 16:23
15F:→ loveme00835: 而且還包含 lifetime 的保證, 你可以看這個範例 04/14 16:24
17F:→ loveme00835: 收到一個 const T&, 你需要保證/可以假設它在某段區 04/14 16:28
18F:→ loveme00835: 間內都是活著的(意即可以透過這個 ref 去存取它) 04/14 16:29
19F:→ loveme00835: 所以你可以想像如果兩種版本的 getModule() 回傳值和 04/14 16:57
20F:→ loveme00835: this 不同調的衝突在哪裡 (用多個 thread 的角度來看 04/14 16:58
21F:→ loveme00835: ) 至於為什麼要有兩個版本? 其實就是想兩種不同語意 04/14 16:59
22F:→ loveme00835: 下都能叫用, 只是能提供的保證不同 04/14 16:59
例子我懂了, const T& 延長了那個暫時物件的 lifetime,保證它一定存在
不過它這裡是 getModule 是傳回 pointer 耶,用 pointer 會有保證的效果嗎?
多個 thread 的情況,要獲得保證一定要先呼叫 getContextLock 才行吧?
※ 編輯: Lipraxde (140.113.56.71), 04/14/2019 20:29:06
23F:→ loveme00835: 對指標 de-ref 也是一樣的, 除了原本 lifetime 的保 04/14 21:08
24F:→ loveme00835: 證, 另外還有 nullable 的語意, 算是不好的介面設計 04/14 21:09
25F:→ loveme00835: 多個 thread 的情況下, 簡單舉個例子: 對於同樣的int 04/14 21:09
26F:→ loveme00835: 物件, thread a 拿到的如果是 int*, thread b 拿到的 04/14 21:10
27F:→ loveme00835: 是 const int&, 那麼這邊就有一個隱含的語意: 在 b 04/14 21:11
28F:→ loveme00835: 結束存取之前, a 都不可以把這個物件給 delete 掉 04/14 21:11
29F:→ loveme00835: 不過這算是和 execution model 相關的討論, 簡單的作 04/14 21:14
30F:→ loveme00835: 法就是 read/write 都用鎖, 存取前確認合法性, 這樣 04/14 21:14
31F:→ loveme00835: 就能確保正確性 04/14 21:15
假如是用 int& 就沒有這個保證了嗎?
我看了 Lifetime of temporaries bound to references,裡面寫到:
For any statement explicitly binding a reference to a temporary, the lifetime
of all temporaries in the statement are extended to match the lifetime of the
reference.
似乎跟有沒有 const 修飾沒有關係呀,還是說這個是在講不同的事?
※ 編輯: Lipraxde (140.113.56.71), 04/15/2019 00:03:32
32F:→ loveme00835: bind to temporary 是一回事, 而延長 lifetime 就是 04/15 00:09
33F:→ loveme00835: 為了達成我所說的保證, 也就是 const T& 背後帶來的 04/15 00:10
34F:→ loveme00835: 目的 04/15 00:10
35F:→ loveme00835: 不只是 "有/無 const" 這樣表面上的問題 04/15 00:11
36F:→ loveme00835: int& 算是 caller/callee 之間需要協議好這個物件的 04/15 00:42
37F:→ loveme00835: 生命週期是如何, 也許到 callee 的某個時間點就無法 04/15 00:43
38F:→ loveme00835: de-ref, 而 const int& 給的語意更為強烈, 也就是在 04/15 00:44
39F:→ loveme00835: callee 呼叫結束前物件都是可用的, 除了無法透過 ref 04/15 00:45
40F:→ loveme00835: 去 modify, 其實 caller 還有一個責任是 callee 觀察 04/15 00:45
41F:→ loveme00835: 到的物件行為到呼叫結束前必須不變 04/15 00:46
就我對 reference 的理解來說:
int&
// 參考到某個 int
const int&
// 參考到某個 const int
考慮到 lifetime 的保證,那就是:
int&
// 參考到某個 int,這個參考可能在某個時間點後就不能相信它了
const int&
// 參考到某個 const int,由於目標是個 const,不會變,所以【可以/要】
// 保證這個參考有效
是說這個 const 用來修飾 int,為什麼要去影響 reference 的有效性?
可以保證有效,但是一定要做出這個保證?
※ 編輯: Lipraxde (140.113.56.71), 04/15/2019 02:13:02
42F:→ loveme00835: 在函式中, 我們把 callee 以及 caller 角色分開, 04/15 02:58
43F:→ loveme00835: callee 加上 const 修飾, 即是和 caller 要求對應的 04/15 02:59
44F:→ loveme00835: 保證, 當然 caller 可以不理會, 譬如接收 const Foo& 04/15 03:00
45F:→ loveme00835: 然後進行兩次 foo.getXXX() 呼叫, 這時候 callee 預 04/15 03:01
46F:→ loveme00835: 期不管呼叫再多次得到的值都要是相同的. 這就是加上 04/15 03:02
47F:→ loveme00835: const 會需要 caller 做出的保證, 所以不單單只是 04/15 03:02
48F:→ loveme00835: callee 不想改它的值這麼簡單 04/15 03:02
49F:→ loveme00835: 所以簡單說 const 不只是描述 "存取方式", 也描述了 04/15 03:05
50F:→ loveme00835: "存取的一致性", 當然也包含 lifetime 04/15 03:05
51F:→ loveme00835: 那回來看 getModule() 回傳 const Module* 即是它給 04/15 03:13
52F:→ loveme00835: 出的保證: 在 this 為 const ThreadSafeModule* 的情 04/15 03:13
53F:→ loveme00835: 況下 (const member function), 取得的 Module 物件 04/15 03:13
54F:→ loveme00835: 行為是不變的 (包含 lifetime) 04/15 03:13
56F:→ Lipraxde: 接收 const Foo&,呼叫 foo.getXXX()多次,預期拿到相 04/15 03:40
57F:→ Lipraxde: 同的物件,由於這個物件屬於 foo,所以也要是 const 物 04/15 03:40
58F:→ Lipraxde: 件,不然 foo 就失去 const 的性質了 04/15 03:40
59F:→ Lipraxde: 這樣說得算是完整了嗎? 04/15 03:53
60F:→ loveme00835: 對喔, 這是因為 owning 語意的關係, 如果這個物件不 04/15 03:58
61F:→ loveme00835: 屬於 foo, 那就沒必要維持 const 語意 04/15 03:59
62F:→ Lipraxde: 既然 callee 要求對應的保證,那 Compiler 可以優化它 04/15 04:04
63F:→ Lipraxde: ?可是加了優化後得到的輸出還是有看到 i 被改成 1。Co 04/15 04:04
64F:→ Lipraxde: mpiler 聰明的判斷出這個 caller 沒做出相應的保證,抑 04/15 04:04
65F:→ Lipraxde: 或是這個保證只是給 programmer 看的? 04/15 04:04
66F:→ loveme00835: 因為是參考(指標也是)所以能做的優化有限, 但這個也 04/15 04:14
67F:→ loveme00835: 是 programmer 需要遵守, 屬於語意層面的規範 04/15 04:15
感謝您花這麼多時間回覆,看來是因為 C 沒有 owning 語意,我又忽略掉 const[A 還有
"存取的一致性" 這層意義,才會出現問題2。我應該把 C++ 當門新的語言學才是
※ 編輯: Lipraxde (140.113.56.71), 04/15/2019 20:59:08