|
|
蜊俶婿蜷代Μ繧ケ繝�: 荳ヲ陦悟�逅�キィ Part 4繧ス繝シ繧ケ縺ッGitHub縺ォ遘サ陦後@縺セ縺励◆縲� Non-Blocking Singly-linked List 2(Non-Blocking蜊俶婿蜷代Μ繧ケ繝�)Non-Blocking Slingly-Linked List縺ォ縺、縺�※縲� T.L.Harris迚�縺ョ謾ケ濶ッ縺ァ縺ゅk "Lock-Free Linked Lists and Skip Lists" Mikhail Fomitchev, Eric Ruppert 繧貞ョ溯」�@縺溘� 繧ス繝シ繧ケ縺ッGitHub縺ォ遘サ陦後@縺セ縺励◆縲� 繝��繧ソ讒矩�繝��繧ソ讒矩�list_t縺ィnode_t繧貞ョ夂セゥ縺吶k縲� list_t縺ッList縺ョ譛ャ菴薙]ode_t縺ッList縺ォ騾」邨舌☆繧杵ode縺ョ繝��繧ソ讒矩�縺ァ縺ゅk縲�
node縺ィlist縺ョ繝��繧ソ讒矩�繧堤、コ縺吶� NonBlockingList.h: #define MARKED 0x0001 #define UNMARKED 0x0000 #define MARKED_MASK 0x0001 #define FLAGGED 0x0002 #define UNFLAGGED 0x0000 #define FLAGGED_MASK 0x0002 typedef struct _next_ref { int mark; void *node_ptr; }__attribute__((packed)) next_ref; typedef struct _node_t { lkey_t key; /* key */ val_t val; /* 蛟、 */ struct _node_t *backlink; next_ref succ; /* 谺。縺ョnode縺ク縺ョ繝ェ繝輔ぃ繝ャ繝ウ繧ケ */ }__attribute__((packed)) node_t; typedef struct _list_t { node_t *head; node_t *tail; } list_t; list_t縺ォ縺ッ縲√Μ繧ケ繝医�蜈磯�ュhead縺ィ譛ォ蟆セtail縺檎「コ菫昴&繧後k縲� 蝓コ譛ャ髢「謨ーlist縺ョ逕滓�/* * list_t *init_list(void) * * list繧堤函謌舌☆繧九� * * 謌仙粥縺吶l縺ーlist縺ク縺ョ繝昴う繝ウ繧ソ繧定ソ斐☆縲ょ、ア謨励↑繧丑ULL繧定ソ斐☆縲� * */ list_t *init_list(void) { list_t *list; if ((list = (list_t *) calloc(1, sizeof(list_t))) == NULL) { elog("calloc error"); return NULL; } if ((list->head = (node_t *) calloc(1, sizeof(node_t))) == NULL) { elog("calloc error"); goto end; } if ((list->tail = (node_t *) calloc(1, sizeof(node_t))) == NULL) { elog("calloc error"); goto end; } list->head->key = INT_MIN; list->head->succ.mark = UNMARKED; list->head->succ.node_ptr = (void *)list->tail; list->tail->key = INT_MAX; list->tail->succ.mark = UNMARKED; list->tail->succ.node_ptr = NULL; return list; end: free (list->head); free (list); return NULL; } 繝弱�繝峨�讀懃エ「
inline bool_t cas64(next_ref * addr, const next_ref oldp, const next_ref newp) { char result; __asm__ __volatile__("lock; cmpxchg8b %0; setz %1":"=m"(*addr), "=q"(result) :"m"(*addr), "a"(oldp.mark), "d"(oldp.node_ptr), "b"(newp.mark), "c"(newp.node_ptr) :"memory"); return (((int)result == 0) ? false:true); } #define is_marked_ref(ref) ((ref.mark & MARKED_MASK) == MARKED ? true:false) #define is_unmarked_ref(ref) ((ref.mark & MARKED_MASK) == UNMARKED ? true:false) #define is_flagged_ref(ref) ((ref.mark & FLAGGED_MASK) == FLAGGED ? true:false) #define is_unflagged_ref(ref) ((ref.mark & FLAGGED_MASK) == UNFLAGGED ? true:false) static next_ref make_ref(node_t * node_ptr, const int marked, const int flagged) { next_ref ref; assert(!(marked == MARKED && flagged == FLAGGED)); ref.mark = (marked | flagged); ref.node_ptr = (node_t *) node_ptr; return ref; } #define get_unmarked_ref(node_ptr) make_ref (node_ptr, UNMARKED, UNFLAGGED) #define get_marked_ref(node_ptr) make_ref (node_ptr, MARKED, UNFLAGGED) static void helpMarked (node_t *prev_node, node_t *del_node) { node_t *next_node; assert (del_node->succ.node_ptr != NULL); next_node = del_node->succ.node_ptr; cas64(&prev_node->succ, make_ref(del_node, UNMARKED, FLAGGED), make_ref(next_node, UNMARKED, UNFLAGGED)); } static bool_t searchFrom2 (const lkey_t key, node_t *curr_node, node_t **curr, node_t **next) { node_t *next_node = curr_node->succ.node_ptr; while (next_node->key < key) { while (is_marked_ref(next_node->succ) && (is_unmarked_ref(curr_node->succ) || (curr_node->succ.node_ptr != next_node)) ) { if (curr_node->succ.node_ptr == next_node) helpMarked(curr_node, next_node); next_node = curr_node->succ.node_ptr; } if (next_node->key < key) { curr_node = next_node; next_node = curr_node->succ.node_ptr; } } *curr = curr_node; *next = next_node; return true; } static bool_t tryFlag (node_t *prev_node, node_t *target_node, node_t **result_node) { bool_t ret = true; node_t *del_node; next_ref result; *result_node = NULL; while (1) { if (prev_node->succ.node_ptr == target_node && (is_unmarked_ref(prev_node->succ) && is_flagged_ref(prev_node->succ))) { *result_node = prev_node; return false; } if (cas64(&prev_node->succ, make_ref(target_node, UNMARKED, UNFLAGGED), make_ref(target_node, UNMARKED, FLAGGED)) == true) { *result_node = prev_node; return true; } result = prev_node->succ; if ((result.node_ptr == target_node) && (is_unmarked_ref(result)) && (is_flagged_ref(result))) { *result_node = prev_node; return false; } while (is_marked_ref(prev_node->succ)) { prev_node = prev_node->backlink; } } searchFrom2(target_node->key, prev_node, &prev_node, &del_node); if (del_node != target_node) { ret = false; *result_node = NULL; } return ret; } static void tryMark(node_t *del_node) { node_t *next_node; next_ref result; do { next_node = del_node->succ.node_ptr; cas64(&del_node->succ, make_ref(next_node, UNMARKED, UNFLAGGED), make_ref(next_node, MARKED, UNFLAGGED)); result = del_node->succ; if (is_unmarked_ref(result) && is_flagged_ref(result)) { helpFlagged(del_node, result.node_ptr); } } while (is_unmarked_ref(del_node->succ)); } static void helpFlagged (node_t *prev_node, node_t *del_node) { del_node->backlink = prev_node; if (is_unmarked_ref(del_node->succ)) { tryMark(del_node); } helpMarked(prev_node, del_node); } 繝弱�繝峨�霑ス蜉�
/* * bool_t add(list_t * list, const lkey_t key, const val_t val) * * list縺ォnode(key,val)繧定ソス蜉�縺吶k縲� * 霑ス蜉�菴咲スョ縺ッkey縺ョ譏���↓蠕薙≧縲ゅ☆縺ァ縺ォ蜷後§key繧呈戟縺、node縺後≠繧句�エ蜷医�螟ア謨励� * * 謌仙粥縺吶l縺ーtrue縲∝、ア謨励☆繧後�false繧定ソ斐☆縲� */ bool_t add(list_t * list, const lkey_t key, const val_t val) { node_t *newNode; node_t *prev_node, *next_node; next_ref prev_succ, result; if (searchFrom2(key, list->head, &prev_node, &next_node) != true) return false; if (prev_node->key == key) return false; if ((newNode = create_node(key, val)) == NULL) return false; while (1) { prev_succ = prev_node->succ; if ((prev_succ.mark & FLAGGED_MASK) == FLAGGED) { helpFlagged(prev_node, prev_succ.node_ptr); } else { newNode->succ = make_ref(next_node, UNMARKED, UNFLAGGED); if (cas64(&prev_node->succ, make_ref(next_node, UNMARKED, UNFLAGGED), make_ref(newNode, UNMARKED, UNFLAGGED)) == true) { return true; // return newNode; } else { result = prev_node->succ; if (is_unmarked_ref(result) && is_flagged_ref(result)) { helpFlagged(prev_node, result.node_ptr); } while (is_marked_ref(prev_node->succ)) { prev_node = prev_node->backlink; } } } searchFrom2(key, list->head, &prev_node, &next_node); if (prev_node->key == key) { free (newNode); return false; } } }髢「謨ーadd()蜀�Κ縺ァ蜻シ縺カnode逕滓�髢「謨ーcreate_node()繧堤、コ縺吶� /* * node_t *create_node(const lkey_t key, const val_t val) * * (key, val)繧呈戟縺、node繧堤函謌舌☆繧九� * * 謌仙粥縺吶l縺ーnode縺ク縺ョ繝昴う繝ウ繧ソ繧定ソ斐☆縲ょ、ア謨励☆繧後�NULL繧定ソ斐☆縲� */ static node_t *create_node(const lkey_t key, const val_t val) { node_t *node; if ((node = (node_t *) calloc(1, sizeof(node_t))) == NULL) { elog("calloc error"); return NULL; } node->next = make_ref(NULL, UNMARKED); node->key = key; node->val = val; return node; } 繝弱�繝峨�蜑企勁繝弱�繝峨�蜑企勁繧ょ渕譛ャ謌ヲ逡・縺ッ霑ス蜉�縺ィ蜷後§縺ァ縺ゅk縲� /* * bool_t delete(list_t * list, const lkey_t key, val_t *val) * * list縺九ikey繧呈戟縺、node繧貞炎髯、縺励√◎縺ョnode縺ョval繧�*val縺ォ譖ク縺崎セシ繧縲� * key縺悟ュ伜惠縺励↑縺��エ蜷医�螟ア謨励� * * 謌仙粥縺吶l縺ーtrue縲∝、ア謨励☆繧後�false繧定ソ斐☆縲� */ bool_t delete(list_t * list, const lkey_t key, val_t *val) { node_t *prev_node, *del_node; node_t *result_node; bool_t result; searchFrom2(key, list->head, &prev_node, &del_node); if (del_node->key != key) return false; result = tryFlag(prev_node, del_node, &result_node); if (result_node != NULL) { helpFlagged(result_node, del_node); } if (result == false) return false; *val = del_node->val; free_node(del_node); return true; } 繝弱�繝峨�讀懃エ「/* * bool_t find(list_t * list, const lkey_t key, val_t *val) * * list縺九ikey繧呈戟縺、node繧呈、懃エ「縺励√◎縺ョnode縺ョval繧�*val縺ォ譖ク縺崎セシ繧縲� * key縺悟ュ伜惠縺励↑縺��エ蜷医�螟ア謨励� * * 謌仙粥縺吶l縺ーtrue縲∝、ア謨励☆繧後�false繧定ソ斐☆縲� */ bool_t delete(list_t * list, const lkey_t key, val_t *val) { node_t *prev_node, *del_node; node_t *result_node; bool_t result; searchFrom2(key, list->head, &prev_node, &del_node); if (del_node->key != key) return false; result = tryFlag(prev_node, del_node, &result_node); if (result_node != NULL) { helpFlagged(result_node, del_node); } if (result == false) return false; *val = del_node->val; free_node(del_node); return true; } /* * bool_t find(list_t * list, const lkey_t key, val_t *val) * * list縺九ikey繧呈戟縺、node繧呈、懃エ「縺励√◎縺ョnode縺ョval繧�*val縺ォ譖ク縺崎セシ繧縲� * key縺悟ュ伜惠縺励↑縺��エ蜷医�螟ア謨励� * * 謌仙粥縺吶l縺ーtrue縲∝、ア謨励☆繧後�false繧定ソ斐☆縲� */ bool find(list_t * l, const lkey_t key) { node_t *curr; curr = search(l, key); if ((curr == l->tail) || (curr->key != key)) return false; return true; } 螳溯。�繧ス繝シ繧ケ縺ッGitHub縺ォ遘サ陦後@縺セ縺励◆縲�
Last-modified: 2014-7-6
|