2022q1 Homework5 (quiz6)
contributed by < oucs638 >
測驗題: quiz6
Github: oucs638/linux_2022spring_quiz6
測驗 2 : Lock-free Hash Table
- 此題測驗要補完
hashmap.c
中的程式碼,使程式執行符合預期
- 首先看 hash table 在
hashmap.h
中的資料結構定義
- 每個
hashmap_t
會紀錄 n_buckets
個 single linked list 的首個節點
buckets[i]
可以取用第 i
個 single linked list 的首個節點
- 每個 single linked list 由
hashmap_kv_t
組成,->next
指向下一個節點
KKKK, QQQQ
- 這兩個程式碼片段在
hashmap_put
函式中
- 當 key 值存在,則要檢查該 key 值的 linked list 是否為 head
- 如是,則新的 key 值接在前一個節點之後,故
KKKK = &prev->next
- 如否,則接到 head 之後,故
QQQQ = &map->buckets[bucket_index]
ZZZZ
- 這個程式碼片段在
hashmap_del
函式中
- 當要刪除的 key 值對應的 linked list 存有節點,則要判斷目標節點是否為首個節點
- 如否,則直接修改前一個節點的
next
,故 ZZZZ = &prev->next
延伸問題 1
- 解釋上述程式碼運作原理,並指出其設計和實作的缺失 (如原本只接受 uin32_t 型態的輸入,無法處理字串作為 key)
hashmap_put
中會先判斷 key value 是否已存在 hash table 中
- 如 key value 已存在 hash table 中,則需要判斷 key 是否存在 head (line 28 - 64)
- 如否,則將
prev->next
指向 next
,將新的節點連接上去 (line 36 - 47)
- 如是,則將新的節點接在 head 之後 (line 48 - 63)
- 如 key value 不存在 hash table 中,則將新的節點作為 head (line 64 - 85)
hashmap_del
中會先判斷 key value 是否已存在 hash table 中
- 如否,則回傳
false
(line 18 - 19)
- 如是,則判斷目標節點是否為
head
(line 22 - 43)
- 如否,則將前個節點的
next
指向下個節點 (line 22 - 30)
- 如是,則將下個節點設為
head
(line 31 - 43)
延伸問題 2
Lock-Free Linked Lists and Skip Lists
- 這篇論文討論如何實現 lock-free 的 distributed data structure
- 論文使用 singly-linked list 來實現,並引入 skip list 的結構
- 論文實現的演算法使用 single-word compare & swap synchronization primitive
- 為了實現 lock-free,使個別 process 的 delays 或 failures 不會阻礙其他 process 的執行,論文的實作中使用了 backlinks 和 flag bits 以及 mark 被刪除節點的機制
- backlink 指向被刪除的節點的前一個節點
- 當 flag bit 設為 1,表示下一個節點的刪除正在進行
- backlink 的設計使得被刪除的節點可以復原
- 論文實現的演算法主要有八個部分
Search (Key k): Node
- 如有目標 key 值的節點,則回傳該節點
- 否則,該 key 不存在
SearchFrom (Key k, Node *curr_mode): (Node, Node)
- 回傳兩個相鄰的節點
n1
, n2
,符合 n1.key <= k < n2.key
- 在拜訪節點的同時,會檢查下個節點是否被 mark,並呼叫
HelpMarked
以刪除被 mark 的節點
HelpMarked (Node *prev_node, Node *del_node)
- 嘗試刪除被 mark 的節點
del_node
,並將前一個節點 prev_node
的 flag 設回 0
- 使用 atomic compare and swap 指令進行操作,以確保同時沒有其他 process 對目標節點做更動
Delete (Key k): Node
- 嘗試刪除目標 key 值的節點,使用 three-step deletion
- 首先,呼叫
SearchFrom
搜尋目標 key 值節點,如果該節點存在,則呼叫 TryFlag
嘗試將前一個節點的 flag 設為 1
- 如果
TryFlag
回傳結果不為 null
,則呼叫 HelpFlagged
進行第二步和第三步
HelpFlagged (Node *prev_node, Node *del_node)
- 刪除節點的第二步,將
del_node
的 backlink 指向前一個節點,並呼叫 TryMark
mark del_node
- 刪除節點的第三步,呼叫
HelpMarked
嘗試刪除目標節點
TryMark (Node del_node)
- 嘗試 mark 要刪除的節點
del_node
- 使用 atomic compare ad swap 指令進行操作,以確保同時沒有其他 process 對目標節點做更動
TryFlag (Node *prev_node, Node *target_node): (Node, Boolean)
- 嘗試將要刪除的目標節點的前一個節點 flag 設為 1,並回傳
prev_node
- 使用 atomic compare ad swap 指令進行操作,以確保同時沒有其他 process 對目標節點做更動
- 如果目標節點已刪除,則回傳
null
Insert (Key k, Element e): Node
- 嘗試插入給定 key 值的新節點
- 呼叫
SearchForm
搜尋 key 值插入的位置,並確認 key 值不重複
- 如果要插入的位置前一個節點 flag 為 1,代表後續的節點刪除還未完成,呼叫
HelpFlagged
完成刪除動作
- 如果要插入的位置前一個節點被 mark,表示該節點要被刪除,用 backlinks 往前找到沒有 mark 的節點重新設為
prev_node
- 使用 atomic compare ad swap 指令進行操作,以確保同時沒有其他 process 對目標節點做更動
延伸問題 3