
以åã®ã¡ã¢ã§è¿°ã¹ãããã«ãããã¯ããªãŒããŒã¿æ§é ãå®è£
ããéã®äž»ãªåé¡ã¯ãABAã®åé¡ãšã¡ã¢ãªã®åé€ã§ãã ããã2ã€ã®åé¡ã¯é¢é£ããŠããŸãããç§ã¯å
±æããŠããŸããäºå®ã¯ããã®ãã¡ã®1ã€ã ãã解決ããã¢ã«ãŽãªãºã ããããšããããšã§ãã
ãã®èšäºã§ã¯ãããã¯ããªãŒã³ã³ããã®å®å
šãªã¡ã¢ãªåçãšããŠç¥ãããŠããæ¹æ³ã®æŠèŠã説æããŸãã Michael-Scottã®å€å
žçãªããã¯ããªãŒãã¥ãŒ[MS98]ã§ããã®ã¡ãœãããŸãã¯ãã®ã¡ãœããã®äœ¿ç𿹿³ã瀺ããŸãã
ã¿ã°ä»ããã€ã³ã¿ãŒ
ã¿ã°ä»ããã€ã³ã¿ãŒã¹ããŒã ã¯ãABAã®åé¡ã解決ããããã«IBMã«ãã£ãŠææ¡ãããŸããã ããããããã¯ããã®åé¡ã解決ããããã®æåã®æ¢ç¥ã®ã¢ã«ãŽãªãºã ã§ãã
ãã®ã¹ããŒã ã«ããã°ãåãã€ã³ã¿ãŒã¯ãã¡ã¢ãªã»ã«ã®å®éã®ã¢ãã¬ã¹ãšãã®ã¿ã°ïŒ32ãããæŽæ°ïŒã®åå²äžå¯èœãªãã¢ã§ãã
template <typename T> struct tagged_ptr { T * ptr ; unsigned int tag ; tagged_ptr(): ptr(nullptr), tag(0) {} tagged_ptr( T * p ): ptr(p), tag(0) {} tagged_ptr( T * p, unsigned int n ): ptr(p), tag(n) {} T * operator->() const { return ptr; } };
ã¿ã°ã¯ããŒãžã§ã³çªå·ãšããŠæ©èœããã©ãã«ä»ããã€ã³ã¿ãŒã§ã®åCASæäœäžã«å¢å
ãã ã
ãªã»ãããããããšã¯ãã
ãŸãã ãã€ãŸããå³å¯ã«å¢å ããŸãã ã¢ã€ãã ãç©ççã«åé€ããã®ã§ã¯ãªããã³ã³ããããã¢ã€ãã ãåé€ãããšãã¯ãã¢ã€ãã ã空ãã¢ã€ãã ã®ç©ºããªã¹ããªã¹ãã«é
眮ããå¿
èŠããããŸãã åæã«ãfree-listã«ãããªã¢ãŒãèŠçŽ ã«ã¢ã¯ã»ã¹ããå Žåã¯éåžžã«åãå
¥ããããŸããããã¯ããªãŒæ§é ããããããäžæ¹ã®ã¹ã¬ãããXèŠçŽ ãåé€ããŠããéãããäžæ¹ã®ã¹ã¬ããã¯Xãžã®ã©ãã«ä»ããã€ã³ã¿ãŒã®ããŒã«ã«ã³ããŒãæã¡ãèŠçŽ ã®ãã£ãŒã«ããåç
§ã§ããŸãã ãããã£ãŠãããªãŒãªã¹ãã¯åã¿ã€ãTããšã«åé¢ããå¿
èŠããããããã«ãããªãŒãªã¹ãã«èŠçŽ ãé
眮ãããšãã«ããŒã¿ã¿ã€ãTãã¹ãã©ã¯ã¿ãåŒã³åºãããšã¯å€ãã®å Žåèš±å¯ãããŸããïŒåæã¢ã¯ã»ã¹ã®ããããã¹ãã©ã¯ã¿æäœäžã«å¥ã®ã¹ã¬ããããã®èŠçŽ ããããŒã¿ãèªã¿åãããšãã§ããŸãïŒã
ã¿ã°ä»ããã€ã³ã¿ãŒã¹ããŒã ã«ã¯ãæ¬¡ã®æ¬ ç¹ããããŸãã
- ãã®ã¹ããŒã ã¯ãããã«ã¯ãŒãäžã®CASã¢ãããã¯ããªããã£ãïŒdwCASïŒããããã©ãããã©ãŒã ã«å®è£
ãããŸãã 32ãããã®ææ°ãã©ãããã©ãŒã ã§ã¯ãdwCASã64ãããã¯ãŒãã§åäœãããã¹ãŠã®ææ°ã®ã¢ãŒããã¯ãã£ã«64ãããåœä»€ã®å®å
šãªã»ãããããããããã®èŠä»¶ã¯æºããããŸãã ãã ãã64ãããåäœã¢ãŒãã®å Žåã128ãããïŒãŸãã¯å°ãªããšã96ãããïŒã®dwCASãå¿
èŠã§ããããã¯ããã¹ãŠã®ã¢ãŒããã¯ãã£ã«å®è£
ãããŠããããã§ã¯ãããŸããã
ã¯ããããªãã¯ãã³ã»ã³ã¹ãæžãããç§ã®å人ïŒããã¯ããªãŒã§ç¹ã«æŽç·ŽãããŠããã®ã¯ãã¿ã°ä»ããã€ã³ã¿ãŒãå®è£
ããããã«ã128ãããïŒãŸãã¯96ãããïŒã®åºãCASãæã€å¿
èŠããªããšããããšã«å察ãããããããŸããã ææ°ã®ããã»ããµã¯ã¢ãã¬ã¹æå®ã«48ãããã®ã¿ã䜿çšããŠããããã64ãããã§å¯Ÿå¿ã§ããŸããã¢ãã¬ã¹ã®æäžäœ16ãããã¯ç¡æã§ãã¿ã°ã«ãŠã³ã¿ãŒã®æ ŒçŽã«äœ¿çšã§ããŸãã ãŸãã確ãã«ã圌ãã¯ã§ããŸãã ããã¯
boost.lockfree
ã§è¡ãã
boost.lockfree
ã
ãã®ã¢ãããŒãã«ã¯2ã€ã®ãããããããããŸãã
- å°æ¥ããããã®å€ã16ãããã®ã¢ãã¬ã¹ãé¢ä¿ããªãããšã誰ãä¿èšŒããŸããïŒ ã¡ã¢ãªãããã®åéã§æ¬¡ã®ãã¬ãŒã¯ã¹ã«ãŒãå°æ¥ãããã®éãäžæ¡å¢ãããšããã«ããã³ããŒã¯ããã«å®å
šãª64ãããã¢ãã¬ã¹æå®ã®æ°ããããã»ããµããªãªãŒã¹ããŸã
- ã¿ã°ãä¿æããã«ã¯16ãããã§ååã§ããïŒ ãã®ããŒãã«é¢ãã調æ»ãè¡ããããããã®èª¿æ»ã®çµæã¯æ¬¡ã®ãšããã§ãã16ãããã§ã¯äžååã§ããããªãŒããŒãããŒãçºçããå¯èœæ§ããããABAã®åé¡ã«ã€ãªããå¯èœæ§ããããŸãã ãã ãã32ãããã§ååã§ãã
å®éã16ãããã¯0-65535ã¿ã°ã®å€ã§ããçŸä»£ã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã§ã¯ãã¹ããªãŒã ã«å²ãåœãŠãããã¿ã€ã ã¹ãããã¯300ã50äžã®ã¢ã»ã³ãã©ãŒåœä»€ïŒLinuxéçºè
ã®å
éšéä¿¡ããååŸïŒã§ããããã®ã¯ã©ã³ã¿ã ã¯ããã»ããµãŒããã©ãŒãã³ã¹ã®åäžã«ãã£ãŠã®ã¿æé·ããŸãã 1ã€ã®ã¯ã©ã³ã¿ã ã§ã¯ãCASã®ãããªéãæäœã§ã65,000ãå®è¡ããããšãå¯èœã§ãïŒãŸãã仿¥äžå¯èœãªããææ¥ãå¯èœã§ãïŒã ãããã£ãŠã16ãããã®ã¿ã°ã䜿çšãããšãABAã®åé¡ãçºçããå¯èœæ§ãéåžžã«é«ããªããŸãã
- 空ããªã¹ãã®å®è£
ã¯ãããã¯ããªãŒã¹ã¿ãã¯ãŸãã¯ããã¯ããªãŒãã¥ãŒã§ãããããã©ãŒãã³ã¹ã«ãã€ãã¹ã®åœ±é¿ãäžããŸããã€ãŸããã¢ã€ãã ã空ããªã¹ãããåé€ãããŠè¿œå ããããšãã«ãå°ãªããšããã1åCASåŒã³åºããè¡ãããŸãã äžæ¹ã空ããªã¹ãã空ã§ãªãå Žåã¯ãã·ã¹ãã ã䜿çšããå¿
èŠããªããããéåžžã¯äœéã§åæåãããã¡ã¢ãªå²ãåœãŠæ©èœã®ããã空ããªã¹ããååšãããšçç£æ§ãåäžããŸãã
- åããŒã¿åã«åå¥ã®ç©ºããªã¹ããèšå®ãããšãäžéšã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ã¡ã¢ãªã®äœ¿çšå¹çãäœäžããå¯èœæ§ããããããèŽ
æ²¢ã«ãªããŸãã ããšãã°ãããã¯ããªãŒãã¥ãŒã«å¹³åã§10åã®èŠçŽ ãå«ãŸããŠããããããŒã¯æã«ãã®ãµã€ãºã100äžã«éããå¯èœæ§ãããå ŽåãããŒã¯ã«éããåŸã®ããªãŒãªã¹ãã®ãµã€ãºã¯çŽ100äžã«ãªããŸãã
ãããã£ãŠãã¿ã°ä»ããã€ã³ã¿ãŒã¹ããŒã ã¯ãABAã®åé¡ã®ã¿ã解決ããã¡ã¢ãªã
è§£æŸããåé¡ã解決ããªãã¢ã«ãŽãªãºã ã®äŸã§ãã
libcdsã©ã€ãã©ãªã¯ãçŸåšããã¯ããªãŒã³ã³ãããå®è£
ããããã«ã¿ã°ä»ããã€ã³ã¿ã䜿çšããŠããŸããã æ¯èŒçåçŽã§ããã«ããããããããã®ã¹ããŒã ã¯ãåã³ã³ãããªããžã§ã¯ãã®ç©ºããªã¹ãã®ååšã«ãããã¡ã¢ãªæ¶è²»ã®å¶åŸ¡ãããªãæé·ã«ã€ãªããå¯èœæ§ããããŸãã libcdsã§ã¯ãdwCASã䜿çšããã«ãäºæž¬å¯èœãªã¡ã¢ãªæ¶è²»ã䌎ãããã¯ããªãŒã¢ã«ãŽãªãºã ã«çŠç¹ãåœãŠãŸããã
ã¿ã°ä»ããã€ã³ã¿ãŒã䜿çšããè¯ãäŸã¯ã
boost.lockfree
ã©ã€ãã©ãªãŒã§ãã
ã¿ã°ä»ããã€ã³ã¿ãŒã®äŸ
ã·ãŒãã®ãã¡ã³ïŒååšããå ŽåïŒ-ã¿ã°ä»ããã€ã³ã¿ãŒã䜿çšããæ¬äŒŒã³ãŒã
MSQueue
[MS98]ã ã¯ããããã¯ããªãŒã¢ã«ãŽãªãºã ã¯éåžžã«åé·ã§ãã
ç°¡åã«ããããã«ã
std:atomic
䜿çšãçç¥ããŸããã
template <typename T> struct node { tagged_ptr next; T data; } ; template <typename T> class MSQueue { tagged_ptr<T> volatile m_Head; tagged_ptr<T> volatile m_Tail; FreeList m_FreeList; public: MSQueue() {

ãšã³ãã¥ãŒããã³ããã¥ãŒæäœã®ã¢ã«ãŽãªãºã ã詳ããèŠãŠã¿ãŸãããã ãããã®äŸã䜿çšãããšãããã¯ããªãŒæ§é ãæ§ç¯ãããšãã«ããã€ãã®æšæºçãªããªãã¯ãèŠãããšãã§ããŸãã
äž¡æ¹ã®ã¡ãœããã«ã«ãŒããå«ãŸããŠããããšã¯æ³šç®ã«å€ããŸã-æäœã®å®è³ªçãªéšåå
šäœãæåãããŸã§ç¹°ãè¿ãããŸãïŒãŸãã¯ã空ã®ãã¥ãŒãã
dequeue
ãããªã©ãæ£åžžã«å®è¡ã§ããŸããïŒã ã«ãŒãã®å©ããåãããã®ãããªãã¹ã€ããã£ã³ã°ãã¯ãå
žåçãªããã¯ããªãŒã®ããã°ã©ãã³ã°ææ³ã§ãã
ãã¥ãŒã®æåã®èŠçŽ ïŒ
m_Head
ïŒã¯ãããŒèŠçŽ ïŒãããŒããŒãïŒã§ãã ãããŒèŠçŽ ã䜿çšãããšããã¥ãŒã®å
é ãšæ«å°Ÿãžã®ãã€ã³ã¿ã
NULL
ãªããªãããšãä¿èšŒãã
NULL
ã 空ã®ãã¥ãŒã®å
åã¯ã
m_Head == m_Tail && m_Tail->next == NULL
ãšããæ¡ä»¶
m_Head == m_Tail && m_Tail->next == NULL
ïŒè¡D6-D8ïŒã æåŸã®æ¡ä»¶ïŒ
m_Tail->next == NULL
ïŒã¯å¿
é ã§ãããã¥ãŒã«è¿œå ããããã»ã¹äžã«
m_Tail
倿Žããªããã ãè¡E9ã¯
m_Tail->next
ã®ã¿ã倿Žãã
m_Tail->next
ã§ãã ãããã£ãŠãäžèŠã
enqueue
ã¡ãœããã¯ãã¥ãŒã®æ§é ã«éåããŠããŸãã å®éã
m_Tail
ããŒã«ã¯å¥ã®ã¡ãœãããå¥ã®ã¹ã¬ããã§
m_Tail
ããŸãããšã¬ã¡ã³ãã远å ããåã®
enqueue
æäœã¯ã
m_Tail
ãæåŸã®ãšã¬ã¡ã³ãïŒã€ãŸã
m_Tail->next == NULL
ïŒãæãããšããã§ãã¯ããŸãïŒE8è¡ïŒãã®ããããã€ã³ã¿ãŒãæåŸã«ç§»åããããšããŠããŸãïŒE12è¡ïŒã åæ§ã«ãã峿ã®çŸ©åããå®è¡ããåã®
dequeue
æäœã¯ããã¥ãŒã®æåŸãæããŠããªãå Žåã
m_Tail
倿ŽããŸãïŒè¡D9ïŒã ããã¯ãããã¯ããªãŒããã°ã©ãã³ã°ã®äžè¬çãªã¢ãããŒãã瀺ããŠããŸã-ã¹ã¬ããéã®çžäºæ¯æŽïŒ
æ¯æŽ ïŒïŒ1ã€ã®æäœã®ã¢ã«ãŽãªãºã ã¯ãã³ã³ãããŒã®ãã¹ãŠã®æäœã«å¯ŸããŠãã¹ãã¢ãããã1ã€ã®æäœã¯ããã®æäœãïŒããããå¥ã®ïŒæäœãžã®æ¬¡ã®åŒã³åºããå®äºãããšããäºå®ã«å€§ããäŸåããŠããŸãå€åïŒå¥ã®ã¹ã¬ããã
å¥ã®åºæ¬çãªèгå¯ïŒæäœã¯ãæäœããå¿
èŠããããã€ã³ã¿ãŒã®å€ãããŒã«ã«å€æ°ã«æ ŒçŽããŸãïŒè¡E5-E6ãD2-D4ïŒã 次ã«ïŒè¡E7ãD5ïŒãèªã¿åãããå€ãå
ã®å€ãšæ¯èŒãããŸã-å
žåçãªããã¯ããªãŒã®ããªãã¯ãéç«¶åããã°ã©ãã³ã°ã«ã¯äžèŠã§ãïŒèªã¿åãããçµéããæéã®éã«ãå
ã®å€ã倿Žãããå¯èœæ§ããããŸãã ã³ã³ãã€ã©ãŒããã¥ãŒã®å
±æããŒã¿ãžã®ã¢ã¯ã»ã¹ãæé©åããªãããã«ããã«ã¯ïŒãããŠãã¹ããŒãããããã³ã³ãã€ã©ãŒã¯E7ãŸãã¯D5ã®æ¯èŒè¡ãå®å
šã«åé€ã§ããŸãïŒã
m_Head
++
m_Head
ãš
m_Tail
ã¯C ++ 11ã§
atomic
ã«å®£èšããå¿
èŠããããŸãïŒæ¬äŒŒã³ãŒã
m_Tail
ããã«ãCASããªããã£ãã¯ã¿ãŒã²ããã¢ãã¬ã¹ã®å€ãæå®ããããã®ãšæ€èšŒããããããçããå Žåãã¿ãŒã²ããã¢ãã¬ã¹ã®ããŒã¿ãæ°ããå€ã«å€æŽããããšãæãåºããŠãã ããã ãããã£ãŠãCASããªããã£ãã®å Žåãåžžã«çŸåšã®å€ã®ããŒã«ã«ã³ããŒãæå®ããå¿
èŠããããŸãã
CAS(&val, val, newVal)
åŒã³åºãã¯
ã»ãšãã©åžžã«æå
ããŸãããããã¯ç§ãã¡ã«ãšã£ãŠééãã§ãã
次ã«ã
dequeue
ã¡ãœããã§
dequeue
ãã³ããŒããã
ãšããèŠãŠã¿ãŸãããïŒè¡D11ïŒïŒã¢ã€ãã ããã¥ãŒããé€å€ããã
å ïŒè¡D12ïŒã èŠçŽ ã®äŸå€ïŒè¡D12ã®
m_Head
åé²ïŒã倱æããå¯èœæ§ãããå ŽåãããŒã¿ã®ã³ããŒïŒD11ïŒãç¹°ãè¿ãããšãã§ããŸãã C ++ã®èгç¹ããèŠããšãããã¯ããã¥ãŒã«æ ŒçŽãããŠããããŒã¿ãè€éãããªãããšãæå³ããŸãããããªããšãD11è¡ã®ä»£å
¥æŒç®åã®ãªãŒããŒãããã倧ãããªããããŸãã ãããã£ãŠãé«è² è·æ¡ä»¶äžã§ã¯ãCASããªããã£ãã®æ
éã®å¯èœæ§ãé«ããªããŸãã D11è¡ãã«ãŒãå€ã«ç§»åããŠã¢ã«ãŽãªãºã ããæé©åãããããšãããšããšã©ãŒãçºçããŸãã
next
èŠçŽ ã¯å¥ã®ã¹ã¬ããã«ãã£ãŠåé€ãããå¯èœæ§ããããŸãã åé¡ã®ãã¥ãŒã®å®è£
ã¯ãèŠçŽ ãåé€ãããããšã®ãªãã¿ã°ä»ããã€ã³ã¿ãŒã¹ããŒã ã«åºã¥ããŠããããããã®ãæé©åãã«ãããïŒD12è¡ã®æ£åžžãªå®è¡æã«ãã¥ãŒã«ãã£ãããŒã¿ã§ã¯ãªãïŒ
äžæ£ãªããŒã¿ãè¿ãããšãã§ããŸãã
MïŒSãã¥ãŒã®æ©èœäžè¬çã«ã MSQueue
ã¢ã«ãŽãªãºã MSQueue
ã m_Head
åžžã«ãããŒããŒããæãã空ã§ãªããã¥ãŒã®æåã®èŠçŽ ãm_Head
次ã®èŠçŽ ã§ãããšããm_Head
ã§ãã dequeue
äžã«ãæåã®èŠçŽ ã®å€ã空ã§ãªããã¥ãŒãã€ãŸãm_Head.next
ããèªã¿åããããããŒèŠçŽ ãåé€ãããæ¬¡ã®èŠçŽ ãæ°ãããããŒèŠçŽ ïŒããã³æ°ãããããïŒãã€ãŸãå€ãè¿ãããèŠçŽ ã«ãªããŸãã æ¬¡ã® dequeue
æäœã®åŸã§ã®ã¿ãèŠçŽ ãç©ççã«åé€ã§ããããšãdequeue
ãŸã ã
䟵å
¥ããŒãžã§ã³ã®cds::intrusive::MSQueue
ã䜿çšããå Žåããã®æ©èœã¯é¢åã§ãã
ãšããã¯ããŒã¹ã®ã¬ã¯ã©ã¡ãŒã·ã§ã³
Fraser [Fra03]ã¯ããšããã¯ããŒã¹ã®ã¹ããŒã ãææ¡ããŸããã é
å»¶åé€ã¯ãåé€ãããèŠçŽ ãžã®ãªã³ã¯ãã¹ã¬ããã«ååšããªããšããå®å
šãªç¢ºä¿¡ãåŸãããå®å
šãªç¬éã«é©çšãããŸãã ãã®ä¿èšŒã¯
ãšããã¯ã«ãã£ãŠæäŸãããŸã
nGlobalEpoch
ã°ããŒãã«æä»£ã
nGlobalEpoch
ãåã¹ã¬ããã¯
nThreadEpoch
ç¬èªã®ããŒã«ã«æä»£ã§
nThreadEpoch
ãŸãã ãšããã¯ããŒã¹ã®ã¹ããŒã ã§ä¿è·ãããã³ãŒããå
¥åãããšããããŒã®ããŒã«ã«ãšããã¯ã¯ãã°ããŒãã«ãšããã¯ãè¶
ããªãå Žåã«å¢åãããŸãã ãã¹ãŠã®ã¹ã¬ãããã°ããŒãã«æä»£ã«
nGlobalEpoch
ã
nGlobalEpoch
å¢åãããŸãã
ã¹ããŒãã®æ¬äŒŒã³ãŒãïŒ
ãªãªãŒã¹ãããããã¯ããªãŒã³ã³ããèŠçŽ ã¯ãåé€ãåŸ
æ©ããŠããã¢ã€ãã ã®ã¹ã¬ããããŒã«ã«ãªã¹ãã«é
眮ãããŸã
m_arrRetired[m_nThreadEpoch % EPOCH_COUNT]
ã ãã¹ãŠã®ãããŒã
m_nGlobalEpoch
ã°ããŒãã«ãšããã¯ãééãããšããã«ããã¹ãŠã®
m_nGlobalEpoch â 1
ãšããã¯ãããŒã®ãã¹ãŠã®ãªã¹ããè§£æŸãããã°ããŒãã«ãšããã¯èªäœãå¢åãããŸãã
UPD 2016UPD 2016ïŒãã®ç䌌ã³ãŒãã®ãšã©ãŒãææããŠããã
perfhunterã«æè¬ããŸãã
ãããã¯ããªãŒããŒã¿æ§é ããã®èšäºã®å°ããªãšã©ãŒãä¿®æ£ããŠãã ããã å
åŽã ã¡ã¢ãªãŒç®¡çã¹ããŒã ã-exitïŒïŒé¢æ°ã®ããšããã¯ããŒã¹ã®åçãã»ã¯ã·ã§ã³ã§ãm_arrRetired [ïŒm_nGlobalEpoch-2ïŒïŒ
EPOCH_COUNT]ãm_arrRetired [ïŒm_nGlobalEpoch-1ïŒïŒ
EPOCH_COUNT]ã«çœ®ãæããŸãã ãã®æç¹ã§ãã¹ããªãŒã ã®ããŒã«ã«æä»£ã¯m_nGlobalEpochïŒãã§ã«å
¥åããã¹ããªãŒã ã®å ŽåïŒenterïŒïŒïŒããŸãã¯m_nGlobalEpoch + 1ïŒã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«å床å
¥åããã¹ããªãŒã ã®å ŽåïŒïŒã§ãããçæm_nGlobalEpoch-1ã¯å®å
šã«è§£æŸã§ããŸãã
åããã¯ããªãŒã³ã³ãããŒæäœã¯ãã¯ãªãã£ã«ã«ã»ã¯ã·ã§ã³ã«éåžžã«äŒŒãŠãã
ThreadEpoch::enter()
ããã³
ThreadEpoch::exit()
åŒã³åºãã«å²ãŸããŠããŸãã
lock_free_op( ⊠) { get_current_thread()->ThreadEpoch.enter() ; . . .
ãã®ã¹ããŒã ã¯éåžžã«åçŽã§ãããŒã«ã«ãªã³ã¯ïŒã€ãŸããã³ã³ãããŒæäœå
ã®ãªã³ã¯ïŒãä¿è·ããŠãã³ã³ãããŒèŠçŽ ãããã¯ããªãŒã«ããŸãã ã¹ããŒã ã¯ïŒã³ã³ãããŒã®æäœã®å€éšããïŒã°ããŒãã«ãªã³ã¯ä¿è·ãæäŸã§ããŸãããã€ãŸããããã¯ããªãŒã³ã³ãããŒã®èŠçŽ ã«å¯Ÿããã€ãã¬ãŒã¿ãŒã®æŠå¿µã¯ããšããã¯ããŒã¹ã®ã¹ããŒã ã䜿çšããŠå®è£
ã§ããŸããã ãã®ã¹ããŒã ã®æ¬ ç¹ã¯ã
ãã¹ãŠã®ããã°ã©ã ãããŒãæ¬¡ã®æä»£ã«ç§»è¡ããå¿
èŠãããããšã§ããã€ãŸããäœããã®ããã¯ããªãŒã³ã³ãããŒã«ç§»è¡ããå¿
èŠããããŸãã å°ãªããšã1ã€ã®ã¹ã¬ãããæ¬¡ã®æä»£ã«ç§»è¡ããªãå Žåãä¿çäžã®ãã€ã³ã¿ãŒã®åé€ã¯çºçããŸããã ã¹ããªãŒã ã®åªå
床ãåãã§ãªãå Žåãåªå
床ã®äœãã¹ããªãŒã ã¯ãåªå
床ã®é«ãã¹ããªãŒã ã®èŠçŽ ãåé€ããããã«ãé
å»¶ãããã¹ããªãŒã ã®ãªã¹ããç¡å¶éã«å¢å€§ãããå¯èœæ§ããããŸãã ãããã£ãŠããšããã¯ããŒã¹ã®ã¹ããŒã ã¯ãç¡å¶éã®ã¡ã¢ãªæ¶è²»ã«ã€ãªããå¯èœæ§ããããŸãïŒã¹ã¬ããã®1ã€ãã¯ã©ãã·ã¥ããå Žåã確å®ã«ã€ãªããïŒã
libcdsã©ã€ãã©ãªã«ã¯ããšããã¯ããŒã¹ã®ã¹ããŒã ã®å®è£
ããããŸããã çç±ïŒãã¹ãŠã®ãããŒãã°ããŒãã«æä»£ã«å°éãããã©ããã倿ããããã®ååã«å¹æçãªã¢ã«ãŽãªãºã ãæ§ç¯ã§ããŸããã§ããã ããããèªè
ã®äžäººã解決çããå§ãããŸããïŒ..
ãã¶ãŒããã€ã³ã¿ãŒ

ãã®ã¹ããŒã ã¯Michael [Mic02aãMic03]ã«ãã£ãŠææ¡ãããããã¯ããªãŒããŒã¿æ§é èŠçŽ ãžã®
ããŒã«ã«ãªã³ã¯ãä¿è·ããããšãç®çãšããŠããŸãã ãããããããã¯æãæåã§ç²Ÿå·§ãªé
å»¶åé€ã®ã¹ããŒã ã§ãã ã¢ãããã¯ãªèªã¿åããšæžã蟌ã¿ã®ã¿ã«åºã¥ããŠãããCASã®ãããªãéããåæããªããã£ãã¯ãŸã£ãã䜿çšããŸããã
ã¹ããŒã ã®åºç€ã¯ãã³ã³ããã®ããã¯ããªãŒèŠçŽ ãžã®ãã€ã³ã¿ããããŒã¿æ§é ã®ããã¯ããªãŒæäœå
ã§
ãã¶ãŒã ïŒå±éºïŒãšããŠå®£èšãã矩åã§ããã€ãŸããèŠçŽ ãžã®ãã€ã³ã¿ãæäœããåã«ãçŸåšã®ã¹ããªãŒã ã®ãã¶ãŒããã€ã³ã¿ã®
HP
é
åã«å
¥ããå¿
èŠããããŸãã
HP
ã¢ã¬ã€ã¯ãã¹ããªãŒã ã«å¯ŸããŠãã©ã€ããŒãã§ããææè
ã¹ããªãŒã ã®ã¿ãã¹ããªãŒã ã«æžã蟌ã¿ããã¹ãŠã®ã¹ããªãŒã ã¯ïŒ
Scan
æé ã§ïŒèªã¿åãããšãã§ããŸãã ããŸããŸãªããã¯ããªãŒã³ã³ããã®åäœãæ³šææ·±ãåæãããšã
HP
ã¢ã¬ã€ã®ãµã€ãºïŒã¹ã¬ããããšã®ãã¶ãŒããã€ã³ã¿ãŒã®æ°ïŒã3-4ãè¶
ããªããããåè·¯ãç¶æããããã®ãªãŒããŒããããå°ããããšã«æ°ä»ãã§ãããã
巚倧ãªããŒã¿æ§é å
¬å¹³ã«ã¯ã64ãè¶
ãããã¶ãŒããã€ã³ã¿ãŒãå¿
èŠãšããã巚倧ãªãããŒã¿æ§é ãããããšã«æ³šæããŠãã ããã äŸã¯skip-listïŒ cds::container::SkipListMap
ïŒ-確ççããŒã¿æ§é ãå®éã«ã¯åèŠçŽ ã®å¯å€ã®é«ããæã€ãªã¹ãã®ãªã¹ãã§ãã libcdsã«ã¯ãã®ã¹ããŒã ã®ã¹ããããªã¹ãå®è£
ããããŸããããã®ãããªã³ã³ãããŒã¯ãã¶ãŒããã€ã³ã¿ãŒã¹ããŒã ã«ã¯ããŸãé©ããŠããŸããã
ãã¶ãŒããã€ã³ã¿ãŒæ¬äŒŒã³ãŒã[Mic02]ïŒ
ããã¯ãªãã®
pNode
ã³ã³ããèŠçŽ ã®
RetireNode(pNode)
ãåé€ãããšãã¹ããªãŒã
j
ã¯
dlist
ä¿çïŒåé€ãå¿
èŠïŒèŠçŽ ã®
dlist
ããŒã«ã«ïŒã¹ããªãŒã
j
ïŒãªã¹ãã«
dlist
ãŸãã
dlist
ã®ãµã€ãºã
Rã«éãããšïŒ
R㯠N = P*K
ã«å¹æµããŸããã
Nãè¶
ããŸããããšãã°
R = 2N
ïŒã
Scan()
ããã·ãŒãžã£ãåŒã³åºãããä¿çäžã®ã¢ã€ãã ã®åé€ãè¡ãããŸãã æ¡ä»¶
R > P*K
ã¯å¿
é ã§ãããã®æ¡ä»¶ãæºããããå Žåã«ã®ã¿ã
Scan()
ãä¿çäžã®ããŒã¿é
åãããã¹ãŠãåé€ã§ããããšãä¿èšŒãããŸãã ãã®æ¡ä»¶ã«éåãããšã
Scan()
ã¯é
åããäœãåé€ããªãå¯èœæ§ããããã¢ã«ãŽãªãºã ãšã©ãŒãçºçããŸããé
åã¯å®å
šã«ãã£ã±ãã§ããããµã€ãºãå°ããããããšã¯ã§ããŸããã
Scan()
ã¯4ã€ã®ã¹ããŒãžã§æ§æãããŸãã
- ãŸããçŸåšã®ãã¶ãŒããã€ã³ã¿ãŒã®
plist
é
åãæºåãããŸããããã«ã¯ããã¹ãŠã®ãããŒã®ãã¹ãŠã®énull
ãã¶ãŒããã€ã³ã¿ãŒãå«ãŸãnull
ã å
±æããŒã¿ïŒ HP
ã¹ããªãŒã ã®é
åïŒãèªã¿åãã®ã¯æåã®ã¹ããŒãžã®ã¿ã§ãæ®ãã®ã¹ããŒãžã¯ããŒã«ã«ããŒã¿ã§ã®ã¿æ©èœããŸãã - ã¹ããŒãž2ã¯ã
plist
é
åããœãŒãããŠãåŸç¶ã®æ€çŽ¢ãæé©åããŸãã ããã§ã plist
ããplist
èŠçŽ ãåé€plist
ããšãã§ãplist
ã - ã¹ããŒãž3-èªèº«ã®åé€ïŒçŸåšã®ã¹ããªãŒã ã®
dlist
é
åã®ãã¹ãŠã®èŠçŽ ã衚瀺ãããŸãã dlist[i]
èŠçŽ ãplist
ïŒã€ãŸããäžéšã®ã¹ã¬ããããã®ãã€ã³ã¿ãŒããã¶ãŒããã€ã³ã¿ãŒãšããŠå®£èšããããšã§æ©èœããå ŽåïŒããããåé€ããããšã¯ã§ããã dlist
ïŒ new_dlist
転éããnew_dlist
ïŒã ããããªããšã dlist[i]
èŠçŽ ãåé€ãããå¯èœæ§ããããŸã-åäžã®ã¹ã¬ããã§ã¯æ©èœããŸããã - ã¹ããŒãž4ã¯ãåé€ãããŠããªãã¢ã€ãã ã
new_dlist
ããnew_dlist
ã«dlist
ãŸãã R > N
, Scan()
dlist
, - .
Hazard Pointer, , :
std::atomic<T *> atomicPtr ; ⊠T * localPtr ; do { localPtr = atomicPtr.load(std::memory_order_relaxed); HP[i] = localPtr ; } while ( localPtr != atomicPtr.load(std::memory_order_acquire));
atomicPtr
localPtr
( )
HP[i]
HP
hazard- . , ,
atomicPtr
, ,
atomicPtr
localPtr
. ,
HP
( hazard)
atomicPtr
. Hazard Pointer' ( hazard), , .
Hazard Pointer (HP-) C++11 memory ordering [Tor08].
MSQueue Hazard PointerLock-free - [MS98] Hazard Pointer. ââ , libcds:
template <typename T> class MSQueue { struct node { std::atomic<node *> next ; T data; node(): next(nullptr) {} node( T const& v): next(nullptr), data(v) {} }; std::atomic<node *> m_Head; std::atomic<node *> m_Tail; public: MSQueue() { node * p = new node; m_Head.store( p, std::memory_order_release ); m_Tail.store( p, std::memory_order_release ); } void enqueue( T const& data ) { node * pNew = new node( data ); while (true) { node * t = m_Tail.load(std::memory_order_relaxed);
Hazard Pointer ?
? , , â . : hazard pointer'
K . â hazard pointer â , , , hazard- . , hazard-. â [Har01]. , HP- .
, HP-
hazard-. , . libcds , , , HP-. , â
Pass the Buck , â Hazard Pointer, hazard-. .
Hazard Pointer libcds

hazard pointer libcds. â
Hazard Pointer Manager â , libcds.dll/.so. â
Thread HP Manager , â HP hazard pointer'
K ()
Retired R .
Thread HP Manager .
P . libcds:
- hazard-
K = 8
P = 100
- ( )
R = 2 * K * P = 1600
.
libcds HP- :
- â (
cds::gc::hzp
). ( T
), . , ( , «» â . , â -, â « ». , , â ). - â ,
cds::gc::hzp
. (template) - , (- type erasure). - (API) â
cds::gc::HP
. , ( ) lock-free libcds, , ( , ) GC
. cds::gc::HP
â .
«» , , , ? : (, retired) :
struct retired_ptr { typedef void (* fnDisposer )( void * ); void * ptr ;
(
retired ) .
Scan()
HP-
pDisposer(ptr)
«» .
pDisposer
. . , :
template <typename T> struct make_disposer { static void dispose( void * p ) { delete reinterpret_cast<T *>(p); } }; template <typename T> void retire_ptr( T * p ) {
, , , .
HP- libcds,
main()
cds::gc::HP
, , HP-,
. , ,
cds::gc::HP
. API HP-.
API cds::gc::HPcds::gc::HP
â , , .
- ã³ã³ã¹ãã©ã¯ã¿ãŒ
HP(size_t nHazardPtrCount = 0, size_t nMaxThreadCount = 0, size_t nMaxRetiredPtrCount = 0, cds::gc::hzp::scan_type nScanType = cds::gc::hzp::inplace);
nHazardPtrCount
â hazard pointer' ( K )
nMaxThreadCount
â ( P )
nMaxRetiredPtrCount
â retired- ( R = 2KP
)
nScanType
â : cds::gc::hzp::classic
, Scan
; cds::gc::hzp::inplace
Scan()
new_dlist
dlist
( ).
, cds::gc::HP
. , cds::gc::HP
Hazard Pointer, , , .
- retired ( )
template <class Disposer, typename T> static void retire( T * p ) ; template <typename T> static void retire( T * p, void (* pFunc)(T *) )
Disposer
( pFunc
) (). :
struct Foo { ⊠}; struct fooDisposer { void operator()( Foo * p ) const { delete p; } };
static void force_dispose();
Scan()
Hazard Pointer. , , libcds .
,
cds::gc::HP
:
thread_gc
â (thread data), Hazard Pointer. , HP- , ,Guard
â hazard pointertemplate <size_t Count> GuardArray
â hazard pointer'. HP- hazard- . , Guard
Guard
GuardArray<N>
Hazard Pointer, . .
Guard
hazard- API:
template <typename T> T protect( CDS_ATOMIC::atomic<T> const& toGuard ); template <typename T, class Func> T protect( CDS_ATOMIC::atomic<T> const& toGuard, Func f );
( T
â ) hazard. , : toGuard
, hazard pointer' , .
( Func
) , hazard T *
, . , (node), (, node
). Func
:
struct functor { value_type * operator()( T * p ) ; };
, hazard.
template <typename T> T * assign( T * p ); template <typename T, int Bitmask> T * assign( cds::details::marked_ptr<T, Bitmask> p );
p hazard. , protect
, , â p
hazard-.
cds::details::marked_ptr
. marked- 2-3 ( 0 ) , â lock-free . hazard- ( Bitmask
).
, hazard.
template <typename T> T * get() const;
hazard-. .
void copy( Guard const& src );
hazard- src
this
. hazard- .
void clear();
hazard-. Guard
.
GuardArray
API, :
template <typename T> T protect(size_t nIndex, CDS_ATOMIC::atomic<T> const& toGuard ); template <typename T, class Func> T protect(size_t nIndex, CDS_ATOMIC::atomic<T> const& toGuard, Func f ) template <typename T> T * assign( size_t nIndex, T * p ); template <typename T, int Bitmask> T * assign( size_t nIndex, cds::details::marked_ptr<T, Bitmask> p ); void copy( size_t nDestIndex, size_t nSrcIndex ); void copy( size_t nIndex, Guard const& src ); template <typename T> T * get( size_t nIndex) const; void clear( size_t nIndex);
CDS_ATOMIC
â ?
,
std::atomic
. ( ) C++11
atomic
,
CDS_ATOMIC
std
. â
cds::cxx11_atomics
, , libcds- atomic. libcds
boost.atomic
,
CDS_ATOMIC
boost
.
Hazard Pointer with Reference Counter

Hazard Pointer , lock-free . , , , , : hazard-.
, HP- . - HP-, . , (, hazard- ). , hazard-, , HP- .
â «, , ». , â , . , .
, , (reference counting, RefCount). Valois â lock-free â . RefCount- , â , . , RefCount-, lock-free fetch-and-add (,
, â ).
2005 [GPST05], Hazard Pointer RefCount : Hazard Pointers lock-free , RefCount â . HRC (Hazard pointer RefCounting).
Hazard Pointers / , RefCounting- . , (- , . [GPST05]). Hazard Pointers
lock-free , HRC :
void CleanUpNode( Node * pNode); void TerminateNode( Node * pNode);
TerminateNode
pNode
.
CleanUpNode
, ,
pNode
«» ( ) , () ; RefCount- , ,
CleanUpNode
:
void CleanUpNode(Node * pNode) { for (all x where pNode->link[x] of node is reference-counted) { retry: node1 = DeRefLink(&pNode->link[x]);
lock-free ( C++) HRC lock-free . , ,
CleanUpNode
,
, . lock-free , , MultiCAS .
, Hazard Pointers , .
Scan
Hazar Pointers ( ,
CleanUpNode
). : Hazard Pointers (
R > N = P * K
),
Scan
- ( , hazard-), HRC
Scan
- ( â ). ,
Scan
,
CleanUpAll
:
CleanUpNode
,
Scan
.
HRC- libcdsUPD (2016 ): libcds 2.0.0 HRC- ( , ), - , Hazard Pointer.
libcds HRC- HP-. â cds::gc::HRC
. API API cds::gc::HP
. namespace cds::gc::hrc
.
HRC- â â libcds. , lock-free . , , . â â lock-free : -, , . , , HP- , , â lock-free .
, HRC- libcds HP-. , ( ) HP-: HRC- 2-3 , HP-. «», : - Scan
(, - ) CleanUpAll
, retired-.
HRC- libcds HP-like , . HRC- HRC-based HP-based .
Pass the Buck

lock-free , Herlihy & al
Pass-the-Buck (PTB, â â) [HLM02, HLM05], HP- ., .
, HP-, PTB- (guarded, hazard pointer HP-). PTB- ( hazard pointer'). (retired)
Liberate
â
Scan
HP-.
Liberate
, . HP-, retired- , PTB- .
guard' (hazard pointer'): , retired-,
hand-off (â â).
Liberate
, retired- guard', retired- hand-off guard'.
Liberate
hand-off , guard, , , .
[HLM05]
Liberate
: wait-free lock-free. Wait-free dwCAS (CAS ), dwCAS . Lock-free , . (guard' retired-) lock-free
Liberate
, (, retired-, ). , PTB- ,
Liberate
.
,
Liberate
PTB-, HP-. PTB libcds HP- hazard- retired-. : «» HP- , PTB, PTB guard'.
libcdsUPD (2016 ): libcds 2.0.0
cds::gc::DHP
â HP, â pass-the-buck , â Hazard Pointer .
libcds PTB-
cds::gc::PTB
, namespace
cds::gc::ptb
. API
cds::gc::PTB
cds::gc:::HP
, . :
PTB( size_t nLiberateThreshold = 1024, size_t nInitialThreadGuardCount = 8 );
nLiberateThreshold
â Liberate
. retired- , Liberate
nInitialThreadGuardCount
â quard' (, libcds). guard'
ãããã«
safe memory reclamation, Hazard Pointer. HP- lock-free .
lock-free . libcds, , (attach)
GC
libcds. ,
Scan()
/
Liberate()
. â .
â RCU, HP-like , â .
UPD 2016:
Errandir , Hazard Pointer ( HP).
[Fra03] Keir Fraser
Practical Lock Freedom , 2004; technical report is based on a dissertation submitted September 2003 by K.Fraser for the degree of Doctor of Philosophy to the University of Cambridge, King's College
[GPST05] Anders Gidenstam, Marina Papatriantafilou, Hakan Sundell, Philippas Tsigas
Practical and Efficient Lock-Free Garbage Collection Based on Reference Counting , Technical Report no. 2005-04 in Computer Science and Engineering at Chalmers University of Technology and Goteborg University, 2005
[Har01] Timothy Harris
A pragmatic implementation of Non-Blocking Linked List , 2001
[HLM02] M. Herlihy, V. Luchangco, and M. Moir
The repeat offender problem: A mechanism for supporting
dynamic-sized lockfree data structures Technical Report TR-2002-112, Sun Microsystems
Laboratories, 2002.
[HLM05] M.Herlihy, V.Luchangco, P.Martin, and M.Moir
Nonblocing Memory Management Support for Dynamic-Sized Data Structure , ACM Transactions on Computer Systems, Vol. 23, No. 2, May 2005, Pages 146â196.
[Mic02] Maged Michael
Safe Memory Reclamation for Dynamic Lock-Free Objects Using Atomic Reads and Writes , 2002
[Mic03] Maged Michael
Hazard Pointers: Safe Memory Reclamation for Lock-Free Objects , 2003
[MS98] Maged Michael, Michael Scott
Simple, Fast and Practical Non-Bloking and Blocking Concurrent Queue Algorithms , 1998
[Tor08] Johan Torp
The parallelism shift and C++'s memory model , chapter 13, 2008
ããã¯ããªãŒã®ããŒã¿æ§é éå§ããåºæ¬ïŒ
äžïŒ
å€ããïŒ