рд▓реЙрдХ-рдлреНрд░реА рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░рдХреНрдЪрд░реНрд╕ред рдЕрдВрджрд░ред рд╕реНрдореГрддрд┐ рдкреНрд░рдмрдВрдзрди рдпреЛрдЬрдирд╛рдПрдБ


рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдкрд┐рдЫрд▓реЗ рдиреЛрдЯреЛрдВ рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЙрдХ-рдлреНрд░реА рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдореЗрдВ рдореБрдЦреНрдп рдХрдард┐рдирд╛рдЗрдпрд╛рдБ ABA рд╕рдорд╕реНрдпрд╛ рдФрд░ рдореЗрдореЛрд░реА рдбрд┐рд▓реАрдЯ рд╣реИрдВред рдореИрдВ рдЗрди рджреЛ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рддрд╛ рд╣реВрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╡реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВ: рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд╣реИрдВ рдЬреЛ рдЙрдирдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдПрдХ рдХреЛ рд╣рд▓ рдХрд░рддреЗ рд╣реИрдВред
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рд▓реЙрдХ-рдореБрдХреНрдд рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЗ рд▓рд┐рдП рд╕реБрд░рдХреНрд╖рд┐рдд рдореЗрдореЛрд░реА рд░рд┐рдХреНрд▓реЗрдореЗрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рдореБрдЭреЗ рдЬреНрдЮрд╛рдд рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЕрд╡рд▓реЛрдХрди рджреВрдВрдЧрд╛ред рдореИрдВ рдорд╛рдЗрдХрд▓-рд╕реНрдХреЙрдЯ рдХреА рдХреНрд▓рд╛рд╕рд┐рдХ рд▓реЙрдХ-рдлреНрд░реА рдХрддрд╛рд░ [MS98] рдкрд░ рдЗрд╕ рдпрд╛ рдЙрд╕ рдкрджреНрдзрддрд┐ рдХреЗ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░реВрдВрдЧрд╛ред



рдЯреИрдЧ рдХрд┐рдП рдЧрдП рд╕рдВрдХреЗрдд


рдЯреИрдЧ рдХреА рдЧрдИ рдкреЙрдЗрдВрдЯрд░реНрд╕ рд╕реНрдХреАрдо рдЖрдИрдмреАрдПрдо рджреНрд╡рд╛рд░рд╛ ABA рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХреА рдЧрдИ рдереАред рд╢рд╛рдпрдж рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдкрд╣рд▓рд╛ рдЬреНрдЮрд╛рдд рдПрд▓реНрдЧреЛрд░рд┐рджрдо рд╣реИред
рдЗрд╕ рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдкреНрд░рддреНрдпреЗрдХ рдкреЙрдЗрдВрдЯрд░ рдореЗрдореЛрд░реА рд╕реЗрд▓ рдФрд░ рдЙрд╕рдХреЗ рдЯреИрдЧ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрддреЗ рдХреА рдПрдХ рдЕрд╡рд┐рднрд╛рдЬреНрдп рдЬреЛрдбрд╝реА рд╣реИ - рдПрдХ 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; } }; 

рдЯреИрдЧ рдПрдХ рд╕рдВрд╕реНрдХрд░рдг рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ рдФрд░ рд▓реЗрдмрд▓ рдХрд┐рдП рдЧрдП рдкреЙрдЗрдВрдЯрд░ рдкрд░ рдкреНрд░рддреНрдпреЗрдХ рдХреИрд╕ рдСрдкрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдмрдврд╝ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдХрднреА рднреА рд░реАрд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ , рдЕрд░реНрдерд╛рдд рдпрд╣ рд╕рдЦреНрддреА рд╕реЗ рдмрдврд╝рддрд╛ рд╣реИред рдХрдВрдЯреЗрдирд░ рд╕реЗ рдХрд┐рд╕реА рдЖрдЗрдЯрдо рдХреЛ рд╣рдЯрд╛рддреЗ рд╕рдордп, рднреМрддрд┐рдХ рд░реВрдк рд╕реЗ рдЖрдЗрдЯрдо рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдЖрдЗрдЯрдо рдХреЛ рдХреБрдЫ рдореБрдлреНрдд рд╕реВрдЪреА рдореЗрдВ рдореБрдлреНрдд рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЙрд╕реА рд╕рдордп, рдпрд╣ рдХрд╛рдлреА рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИ рдпрджрд┐ рдлреНрд░реА-рд▓рд┐рд╕реНрдЯ рдореЗрдВ рд╕реНрдерд┐рдд рд░рд┐рдореЛрдЯ рдПрд▓реАрдореЗрдВрдЯ рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓реЙрдХ-рдлреНрд░реА рд╕реНрдЯреНрд░рдХреНрдЪрд░ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЬрдм рдПрдХ рдереНрд░реЗрдб рдПрдХреНрд╕ рдПрд▓рд┐рдореЗрдВрдЯ рдХреЛ рд╣рдЯрд╛рддрд╛ рд╣реИ, рддреЛ рджреВрд╕рд░реЗ рдереНрд░реЗрдб рдореЗрдВ рд▓реЗрдмрд▓ рдкреЙрдЗрдВрдЯрд░ рдХреА рдПрдХреНрд╕ рдХреА рд▓реЛрдХрд▓ рдХреЙрдкреА рд╣реЛ рд╕рдХрддреА рд╣реИ рдФрд░ рдПрд▓реАрдореЗрдВрдЯ рдХреЗ рдлреАрд▓реНрдб рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред ред рдЗрд╕рд▓рд┐рдП, рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЯреА рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрд╡рддрдВрддреНрд░ рд╕реВрдЪреА рдЕрд▓рдЧ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдЯреА рдбрд┐рд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХреЛ рдХреЙрд▓ рдХрд░рдирд╛ рдЬрдм рдПрдХ рддрддреНрд╡ рдХреЛ рдлреНрд░реА-рд▓рд┐рд╕реНрдЯ рдореЗрдВ рд░рдЦрдирд╛ рдХрдИ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЕрдиреБрдкрдпреБрдХреНрдд рд╣реИ (рд╕рдорд╡рд░реНрддреА рдкрд╣реБрдВрдЪ рдХреЗ рдХрд╛рд░рдг, рдПрдХ рдЕрдиреНрдп рдзрд╛рдЧрд╛ рд╡рд┐рдзреНрд╡рдВрд╕рдХ рдСрдкрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдЗрд╕ рддрддреНрд╡ рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝ рд╕рдХрддрд╛ рд╣реИ)ред
рдЯреИрдЧ рдХреА рдЧрдИ рдкреЙрдЗрдВрдЯрд░ рдпреЛрдЬрдирд╛ рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдиреБрдХрд╕рд╛рди рд╣реИрдВ:

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЯреИрдЧ рдХреА рдЧрдИ рд╕реВрдЪрдХ рдпреЛрдЬрдирд╛ рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдЬреЛ рдХреЗрд╡рд▓ рдПрдмреАрдП рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддреА рд╣реИ рдФрд░ рд╕реНрдореГрддрд┐ рдХреЛ рдореБрдХреНрдд рдХрд░рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддреА рд╣реИред

Libcds рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд▓реЙрдХ-рдлреНрд░реА рдХрдВрдЯреЗрдирд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЯреИрдЧ рдХрд┐рдП рдЧрдП рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреА рд╣реИред рдЗрд╕рдХреА рд╕рд╛рдкреЗрдХреНрд╖ рд╕рд╛рджрдЧреА рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдпрд╣ рдпреЛрдЬрдирд╛ рдкреНрд░рддреНрдпреЗрдХ рдХрдВрдЯреЗрдирд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдореБрдлреНрдд-рд╕реВрдЪреА рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рдХрд╛рд░рдг рдореЗрдореЛрд░реА рдЦрдкрдд рдореЗрдВ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рд╡реГрджреНрдзрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддреА рд╣реИред Libcds рдореЗрдВ, рдореИрдВрдиреЗ dwCAS рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛, рдЕрдиреБрдорд╛рдирд┐рдд рдореЗрдореЛрд░реА рдЦрдкрдд рдХреЗ рд╕рд╛рде рд▓реЙрдХ-рдлреНрд░реА рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд┐рдпрд╛ред
рдЯреИрдЧ рдХрд┐рдП рдЧрдП рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг boost.lockfree рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИред

рдЯреИрдЧ рдХрд┐рдП рдЧрдП рд╕рдВрдХреЗрдд рдЙрджрд╛рд╣рд░рдг


рд╢реАрдЯ рдХреЗ рдкреНрд░рд╢рдВрд╕рдХ (рдпрджрд┐ рдХреЛрдИ рд╣реЛ) - pseudocode MSQueue [MS98] рдЯреИрдЧ рдХрд┐рдП рдЧрдП рд╕реВрдЪрдХ рдХреЗ рд╕рд╛рдеред рд╣рд╛рдВ, рд▓реЙрдХ-рдлреНрд░реА рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдмрд╣реБрдд рдХреНрд░рд┐рдпрд╛рддреНрдордХ рд╣реИрдВ!
рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ std:atomic рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ 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() { //  dummy node // Head & Tail   dummy node m_Head.ptr = m_Tail.ptr = new node(); } }; void enqueue( T const& value ) { E1: node * pNode = m_FreeList.newNode(); E2: pNodeтАУ>data = value; E3: pNodeтАУ>next.ptr = nullptr; E4: for (;;) { E5: tagged_ptr<T> tail = m_Tail; E6: tagged_ptr<T> next = tail.ptrтАУ>next; E7: if tail == m_Tail { // Tail    ? E8: if next.ptr == nullptr { //       E9: if CAS(&tail.ptrтАУ>next, next, tagged_ptr<T>(node, next.tag+1)) { // ,    E10: break; } E11: } else { // Tail      //   tail    E12: CAS(&m_Tail, tail, tagged_ptr<T>(next.ptr, tail.tag+1)); } } } // end loop //   tail    E13: CAS(&m_Tail, tail, tagged_ptr<T>(pNode, tail.tag+1)); } bool dequeue( T& dest ) { D1: for (;;) { D2: tagged_ptr<T> head = m_Head; D3: tagged_ptr<T> tail = m_Tail; D4: tagged_ptr<T> next = headтАУ>next; // Head, tail  next ? D5: if ( head == m_Head ) { // Queue   tail  ? D6: if ( head.ptr == tail.ptr ) { //  ? D7: if (next.ptr == nullptr ) { //   D8: return false; } // Tail     //   tail D9: CAS(&m_Tail, tail, tagged_ptr<T>(next.ptr, tail.tag+1>)); D10: } else { // Tail  //    CAS,    //  dequeue   next D11: dest = next.ptrтАУ>data; //   head D12: if (CAS(&m_Head, head, tagged_ptr<T>(next.ptr, head.tag+1)) D13: break // ,    } } } // end of loop //   dummy node D14: m_FreeList.add(head.ptr); D15: return true; //  тАУ  dest } 


рдЖрдЗрдП рдПрдиреНрдХреНрдпреВ рдФрд░ рдбреАрдХреНрдпреВ рдСрдкрд░реЗрд╢рди рдХреЗ рдПрд▓реНрдЧреЛрд░рд┐рджрдо рдкрд░ рдПрдХ рдХрд░реАрдм рд╕реЗ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдЙрдирдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЖрдк рд▓реЙрдХ-рдлреНрд░реА рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЗ рд╕рдордп рдХрдИ рдорд╛рдирдХ рдЪрд╛рд▓ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдпрд╣ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рд╣реИ рдХрд┐ рджреЛрдиреЛрдВ рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ рд▓реВрдк рд╣реЛрддреЗ рд╣реИрдВ - рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рдкреВрд░рд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╣рд┐рд╕реНрд╕рд╛ рддрдм рддрдХ рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рдпрд╣ рд╕рдлрд▓ рди рд╣реЛ (рдпрд╛ рд╕рдлрд▓ рдирд┐рд╖реНрдкрд╛рджрди рдЕрд╕рдВрднрд╡ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рдЦрд╛рд▓реА рдХрддрд╛рд░ рд╕реЗ dequeue )ред рд▓реВрдк рдХреА рдорджрдж рд╕реЗ рдРрд╕реА "рд╕реНрд╡реЙрдЯрд┐рдВрдЧ" рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд▓реЙрдХ-рдлреНрд░реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рддрдХрдиреАрдХ рд╣реИред

рдХрддрд╛рд░ рдореЗрдВ рдкрд╣рд▓рд╛ рддрддреНрд╡ ( m_Head рджреНрд╡рд╛рд░рд╛ m_Head ) рдПрдХ рдбрдореА рддрддреНрд╡ (рдбрдореА рдиреЛрдб) рд╣реИред рдПрдХ рдбрдореА рддрддреНрд╡ рд╣реЛрдиреЗ рд╕реЗ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдХрддрд╛рд░ рдХреА рд╢реБрд░реБрдЖрдд рдФрд░ рдЕрдВрдд рдореЗрдВ рд╕рдВрдХреЗрдд рдХрднреА рднреА рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред рдПрдХ рдЦрд╛рд▓реА рдХрддрд╛рд░ рдХрд╛ рдПрдХ рд╕рдВрдХреЗрдд m_Head == m_Tail && m_Tail->next == NULL (рд▓рд╛рдЗрдиреЗрдВ D6-D8) рд╣реИред рдЕрдВрддрд┐рдо рд╕реНрдерд┐рддрд┐ ( m_Tail->next == NULL ) рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдХрддрд╛рд░ рдореЗрдВ рдЬреЛрдбрд╝рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рджреМрд░рд╛рди рд╣рдо m_Tail рдирд╣реАрдВ рдмрджрд▓рддреЗ рд╣реИрдВ , рд▓рд╛рдЗрди E9 рдХреЗрд╡рд▓ m_Tail->next рдмрджрд▓рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ, enqueue рд╡рд┐рдзрд┐ рдХрддрд╛рд░ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд░рддреА рд╣реИред рджрд░рдЕрд╕рд▓, m_Tail рдкреВрдВрдЫ рджреВрд╕рд░реА рд╡рд┐рдзрд┐ рдФрд░ / рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп рдереНрд░реЗрдб рдореЗрдВ рдмрджрд▓ рдЬрд╛рддреА рд╣реИ: рддрддреНрд╡ рдЬрд╛рдБрдЪ (рд▓рд╛рдЗрди E8) рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ enqueue рдСрдкрд░реЗрд╢рди рдЬреЛ рдХрд┐ m_Tail рдЕрдВрддрд┐рдо рддрддреНрд╡ (рдпрд╛рдиреА m_Tail->next == NULL ) рдХреЛ m_Tail->next == NULL , рдФрд░ рдпрджрд┐ рдпрд╣ рдирд╣реАрдВ рд╣реИ рдЗрд╕рд▓рд┐рдП, рд╕реВрдЪрдХ рдХреЛ рдЕрдВрдд рддрдХ рд▓реЗ рдЬрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ (рд▓рд╛рдЗрди E12); рдЗрд╕реА рддрд░рд╣, рдЕрдкрдиреЗ "рддрддреНрдХрд╛рд▓ рдХрд░реНрддрд╡реНрдпреЛрдВ" рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ m_Tail рдмрджрд▓ m_Tail рдпрджрд┐ рдпрд╣ рдХрддрд╛рд░ рдХреЗ рдЕрдВрдд рдореЗрдВ рдЗрдВрдЧрд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ (рд▓рд╛рдЗрди D9)ред рдпрд╣ рд╣рдореЗрдВ рд▓реЙрдХ-рдлреНрд░реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ - рдкреНрд░рд╡рд╛рд╣ рдХреА рдкрд╛рд░рд╕реНрдкрд░рд┐рдХ рд╕рд╣рд╛рдпрддрд╛ ( рд╕рд╣рд╛рдпрддрд╛ ) рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рджреГрд╖реНрдЯрд┐рдХреЛрдг рджрд┐рдЦрд╛рддрд╛ рд╣реИ: рдПрдХ рдСрдкрд░реЗрд╢рди рдХрд╛ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрдВрдЯреЗрдирд░ рдХреЗ рд╕рднреА рд╕рдВрдЪрд╛рд▓рди рдкрд░ "рдзрдмреНрдмрд╛" рд╣реИ рдФрд░ рдПрдХ рдСрдкрд░реЗрд╢рди рдЗрд╕ рддрдереНрдп рдкрд░ рдмрд╣реБрдд рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕рдХрд╛ рд╕рдВрдЪрд╛рд▓рди рдЕрдЧрд▓реЗ рдХреЙрд▓ рджреНрд╡рд╛рд░рд╛ рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ (рд╕рдВрднрд╡рддрдГ рдПрдХ рдФрд░) рдСрдкрд░реЗрд╢рди рдореЗрдВ ( рд╢рд╛рдпрдж) рдПрдХ рдФрд░ рдзрд╛рдЧрд╛ред

рдПрдХ рдЕрдиреНрдп рдореМрд▓рд┐рдХ рдЕрд╡рд▓реЛрдХрди: рд╕рдВрдЪрд╛рд▓рди рд╕реНрдерд╛рдиреАрдп рдмрд┐рдВрджреБрдУрдВ рдореЗрдВ рд╕рдВрдЪрдп рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЙрдиреНрд╣реЗрдВ рд╕рдВрдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рд▓рд╛рдЗрдиреЛрдВ рдХреЛ E5-E6, D2-D4)ред рддрдм (рд░реЗрдЦрд╛рдПрдБ E7, D5), рдореВрд▓ рд░реВрдк рд╕реЗ рдкрдврд╝реЗ рдЧрдП рдореВрд▓реНрдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдореВрд▓ рдХреЗ рд╕рд╛рде рдХреА рдЬрд╛рддреА рд╣реИ - рдПрдХ рдареЗрда рд▓реЙрдХ-рдлреНрд░реА рдЯреНрд░рд┐рдХ, рдЧреИрд░-рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЕрдирд╛рд╡рд╢реНрдпрдХ: рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж рд╕реЗ рдЧреБрдЬрд░реЗ рд╕рдордп рдХреЗ рджреМрд░рд╛рди, рдореВрд▓ рдорд╛рди рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдХрдВрдкрд╛рдЗрд▓рд░ рдХрддрд╛рд░ рдХреЗ рд╕рд╛рдЭрд╛ рдбреЗрдЯрд╛ рддрдХ рдкрд╣реБрдВрдЪ рдХрд╛ рдЕрдиреБрдХреВрд▓рди рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП (рдФрд░ "рд╕реНрдорд╛рд░реНрдЯ" рдХрдВрдкрд╛рдЗрд▓рд░ E7 рдпрд╛ D5 рддреБрд▓рдирд╛ рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИ), m_Head рдФрд░ m_Tail рдХреЛ C ++ 11 (рдЫрджреНрдо-рдХреЛрдб - volatile ) рдореЗрдВ atomic рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдпрд╛рдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ CAS рдЖрджрд┐рдо рджрд┐рдП рдЧрдП рдПрдХ рдХреЗ рд╕рд╛рде рд▓рдХреНрд╖реНрдп рдкрддреЗ рдХреЗ рдореВрд▓реНрдп рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рд╡реЗ рд╕рдорд╛рди рд╣реИрдВ, рддреЛ рд▓рдХреНрд╖реНрдп рдкрддреЗ рдкрд░ рдбреЗрдЯрд╛ рдХреЛ рдПрдХ рдирдП рдореВрд▓реНрдп рдореЗрдВ рдмрджрд▓ рджреЗрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, CAS рдЖрджрд┐рдо рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╣рдореЗрд╢рд╛ рд╡рд░реНрддрдорд╛рди рдорд╛рди рдХреА рдПрдХ рд╕реНрдерд╛рдиреАрдп рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреА рдЪрд╛рд╣рд┐рдП; CAS(&val, val, newVal) рдХреЛ CAS(&val, val, newVal) рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рд╕рдлрд▓ рд╣реЛрдЧрд╛, рдЬреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рдЧрд▓рддреА рд╣реИред

рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ dequeue рдХрдм dequeue рд╡рд┐рдзрд┐ (рд▓рд╛рдЗрди D11) рдореЗрдВ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдЖрдЗрдЯрдо рдХреЛ рдХрддрд╛рд░ (рд▓рд╛рдЗрди D12) рд╕реЗ рдмрд╛рд╣рд░ рд░рдЦрд╛ рдЬрд╛рдПред рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдПрдХ рддрддреНрд╡ рдЕрдкрд╡рд╛рдж (рд▓рд╛рдЗрди D12 рдкрд░ m_Head рдЕрдЧреНрд░рд┐рдо) рд╡рд┐рдлрд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдбреЗрдЯрд╛ (D11) рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред C ++ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдХрддрд╛рд░ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдбреЗрдЯрд╛ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрдиреНрдпрдерд╛ рд▓рд╛рдЗрди D11 рдореЗрдВ рдЕрд╕рд╛рдЗрдирдореЗрдВрдЯ рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдУрд╡рд░рд╣реЗрдб рдмрд╣реБрдд рдмрдбрд╝рд╛ рд╣реЛрдЧрд╛ред рддрджрдиреБрд╕рд╛рд░, рдЙрдЪреНрдЪ рд▓реЛрдб рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреЗ рддрд╣рдд, рд╕реАрдПрдПрд╕ рдЖрджрд┐рдо рдХреА рд╡рд┐рдлрд▓рддрд╛ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдмрдврд╝ рдЬрд╛рддреА рд╣реИред D11 рд▓рд╛рдЗрди рдХреЛ рд▓реВрдк рд╕реЗ рдмрд╛рд╣рд░ рд▓реЗ рдЬрд╛рдХрд░ рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХреЛ "рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝" рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рдиреЗ рд╕реЗ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрдЧреА: next рддрддреНрд╡ рдХреЛ рдХрд┐рд╕реА рдЕрдиреНрдп рдереНрд░реЗрдб рд╕реЗ рд╣рдЯрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЪреВрдВрдХрд┐ рдкреНрд░рд╢реНрди рдореЗрдВ рдХрддрд╛рд░ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЯреИрдЧреЗрдб рдкреЙрдЗрдВрдЯрд░ рд╕реНрдХреАрдо рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рддрддреНрд╡реЛрдВ рдХреЛ рдХрднреА рднреА рдирд╖реНрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ "рдЕрдиреБрдХреВрд▓рди" рдЗрд╕ рддрдереНрдп рдХреЛ рдЬрдиреНрдо рджреЗрдЧрд╛ рдХрд┐ рд╣рдо рдЧрд▓рдд рдбреЗрдЯрд╛ (рдбреА 12 рд▓рд╛рдЗрди рдХреЗ рд╕рдлрд▓ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рд╕рдордп рдХрддрд╛рд░ рдореЗрдВ рдореМрдЬреВрдж рд▓реЛрдЧреЛрдВ рдХреЛ рдирд╣реАрдВ) рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдПрдо рдПрдВрдб рдПрд╕-рдХрддрд╛рд░ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, MSQueue рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдЙрд╕ m_Head рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдЬреЛ рд╣рдореЗрд╢рд╛ рдПрдХ рдбрдореА рдиреЛрдб рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рдЧреИрд░-рдЦрд╛рд▓реА рдХрддрд╛рд░ рдХрд╛ рдкрд╣рд▓рд╛ рддрддреНрд╡ m_Head рдмрд╛рдж рдЕрдЧрд▓рд╛ рддрддреНрд╡ рд╣реИред dequeue рджреМрд░рд╛рди dequeue рдкрд╣рд▓реЗ рддрддреНрд╡ рдХрд╛ рдорд╛рди рдПрдХ рдЧреИрд░-рд░рд┐рдХреНрдд рдХрддрд╛рд░ рд╕реЗ рдкрдврд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ m_Head.next , рдбрдореА рддрддреНрд╡ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЕрдЧрд▓рд╛ рддрддреНрд╡ рдирдпрд╛ рдбрдореА рддрддреНрд╡ (рдФрд░ рдирдпрд╛ рд╣реЗрдб) рдмрди рдЬрд╛рддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд, рдЬрд┐рд╕рдХрд╛ рдореВрд▓реНрдп рд╣рдо рд╡рд╛рдкрд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдЖрдк рдЕрдЧрд▓реЗ dequeue рдСрдкрд░реЗрд╢рди рдХреЗ рдмрд╛рдж рд╣реА рдХрд┐рд╕реА рддрддреНрд╡ рдХреЛ рднреМрддрд┐рдХ рд░реВрдк рд╕реЗ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдпрджрд┐ рдЖрдк cds::intrusive::MSQueue рдХреЗ рдШреБрд╕рдкреИрда рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕рдорд╕реНрдпрд╛ cds::intrusive::MSQueue ред



рдпреБрдЧ-рдЖрдзрд╛рд░рд┐рдд рдкреБрдирд░реНрд╡рд┐рдЪрд╛рд░


рдлреНрд░реЗрдЬрд░ [Fra03] рдиреЗ рдПрдХ рдпреБрдЧ- рдЖрдзрд╛рд░рд┐рдд рдпреЛрдЬрдирд╛ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдХреАред рд╡рд┐рд▓рдВрдмрд┐рдд рд╡рд┐рд▓реЛрдкрди рдХреЛ рдПрдХ рд╕реБрд░рдХреНрд╖рд┐рдд рдХреНрд╖рдг рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдм рдкреВрд░реНрдг рд╡рд┐рд╢реНрд╡рд╛рд╕ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рд╣рдЯрд╛рдП рдЧрдП рддрддреНрд╡ рдХреЗ рд▓рд┐рдВрдХ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдЧрд╛рд░рдВрдЯреА рдпреБрдЧреЛрдВ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рддреА рд╣реИ: nGlobalEpoch рдХрд╛ рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрдЧ рд╣реИ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдереНрд░реЗрдб nThreadEpoch рдЕрдкрдиреЗ рд╕реНрдерд╛рдиреАрдп рдпреБрдЧ рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдпреБрдЧ-рдЖрдзрд╛рд░рд┐рдд рдпреЛрдЬрдирд╛ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд░рдХреНрд╖рд┐рдд рдХреЛрдб рджрд░реНрдЬ рдХрд░рдиреЗ рдкрд░, рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрдЧ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдкреНрд░рд╡рд╛рд╣ рдХрд╛ рд╕реНрдерд╛рдиреАрдп рдпреБрдЧ рдмрдврд╝ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рдмрд╛рд░ рдЬрдм рд╕рднреА рдзрд╛рдЧреЗ рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрдЧ рдореЗрдВ рдкрд╣реБрдВрдЪ рдЧрдП рд╣реИрдВ, рддреЛ nGlobalEpoch ред

рд╕реНрдХреАрдорд╛ рд╕реНрдпреВрдбреЛ рдХреЛрдб:
 //   static atomic<unsigned int> m_nGlobalEpoch := 1 ; const EPOCH_COUNT = 3 ; // TLS data struct ThreadEpoch { //    unsigned int m_nThreadEpoch ; //      List<void *> m_arrRetired[ EPOCH_COUNT ] ; ThreadEpoch(): m_nThreadEpoch(1) {} void enter() { if ( m_nThreadEpoch <= m_nGlobalEpoch ) m_nThreadEpoch = m_nGlobalEpoch + 1 ; } void exit() { if (     ,   m_nGlobalEpoch ) { ++m_nGlobalEpoch ;  (delete)  m_arrRetired[ (m_nGlobalEpoch тАУ 1) % EPOCH_COUNT ]   ; } } } ; 

рд░рд┐рд▓реАрдЬрд╝ рдХрд┐рдП рдЧрдП рд▓реЙрдХ-рдлрд╝реНрд░реА рдХрдВрдЯреЗрдирд░ рддрддреНрд╡реЛрдВ рдХреЛ рдЙрди рдЖрдЗрдЯрдореЛрдВ рдХреА рдереНрд░реЗрдб-рд▓реЛрдХрд▓ рд╕реВрдЪреА рдореЗрдВ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ m_arrRetired[m_nThreadEpoch % EPOCH_COUNT] рд╣рдЯрд╛рдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЬреИрд╕реЗ рд╣реА рд╕рднреА рдкреНрд░рд╡рд╛рд╣ m_nGlobalEpoch рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрдЧ рд╕реЗ m_nGlobalEpoch , рд╕рднреА m_nGlobalEpoch тАУ 1 рдХреА рд╕рднреА m_nGlobalEpoch тАУ 1 рдпреБрдЧ рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдореБрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрдЧ рдореЗрдВ рд╣реА рд╡реГрджреНрдзрд┐ рд╣реЛ рд╕рдХрддреА рд╣реИред
рдпреВрдкреАрдбреА 2016
UPD 2016: рдЗрд╕ рдЫрджреНрдо рдХреЛрдб рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж рдкрд░рдлрд╝реЙрд░реНрдорд░ :

рдХреГрдкрдпрд╛ рд▓реЗрдЦ "рд▓реЙрдХ-рдлреНрд░реА рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ" рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рд╕реА рддреНрд░реБрдЯрд┐ рдХреЛ рдареАрдХ рдХрд░реЗрдВред рдЕрдВрджрд░ред рдореЗрдореЛрд░реА рдкреНрд░рдмрдВрдзрди рдпреЛрдЬрдирд╛рдПрдБ - "рдПрдХреНрдкреЛрдЪ-рдЖрдзрд╛рд░рд┐рдд рдкреБрдирд░реНрд╕реНрдорд░рдг" рдЕрдиреБрднрд╛рдЧ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓реЗрдВ () рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕реНрдерд╛рди рдкрд░, m_arrRetired [(m_nGlobalEpoch - 2)% ┬й_COUNT] рдХреЛ m_arrRetired [(m_nGlobalEpoch - 1)% ┬й_COUNT] рд╕реЗ рдмрджрд▓реЗрдВред рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рдиреАрдп рдпреБрдЧ рдпрд╛ рддреЛ m_nGlobalEpoch рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдЙрди рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЬреЛ рдкрд╣рд▓реЗ рд╣реА рдкреНрд░рд╡реЗрд╢ рдХрд░ рдЪреБрдХреЗ рд╣реИрдВ), рдпрд╛ m_nGlobalEpoch + 1 (рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЦрдВрдб рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдкреНрд░рд╡реЗрд╢ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдзрд╛рд░рд╛рдПрдБ), рдФрд░ рдкреАрдврд╝реА m_nGlobalEpoch - 1 рдХреЛ рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред



рдкреНрд░рддреНрдпреЗрдХ рд▓реЙрдХ-рдлреНрд░реА рдХрдВрдЯреЗрдирд░ рдСрдкрд░реЗрд╢рди ThreadEpoch::enter() рдФрд░ ThreadEpoch::exit() рдХреЙрд▓реНрд╕ рдореЗрдВ рд╕рдВрд▓рдЧреНрди рд╣реИ, рдЬреЛ рдХрд┐ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╕реЗрдХреНрд╢рди рдХреЗ рд╕рдорд╛рди рд╣реИ:
 lock_free_op( тАж ) { get_current_thread()->ThreadEpoch.enter() ; . . . // lock-free  . //    тАЬ тАЭ epoch-based , //     ,     ,   //  . . . . get_current_thread()->ThreadEpoch.exit() ; } 

рдпрд╣ рдпреЛрдЬрдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ рдФрд░ рд╕реНрдерд╛рдиреАрдп рд▓рд┐рдВрдХ (рдЬреЛ рдХрдВрдЯреЗрдирд░ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рднреАрддрд░ рд▓рд┐рдВрдХ рд╣реИ) рдХреЛ рддрд╛рд▓рд╛-рдореБрдХреНрдд рдХрдВрдЯреЗрдирд░ рддрддреНрд╡реЛрдВ рд╕реЗ рдмрдЪрд╛рддрд╛ рд╣реИред рдпрд╣ рдпреЛрдЬрдирд╛ рд╡реИрд╢реНрд╡рд┐рдХ рд▓рд┐рдВрдХ рд╕реБрд░рдХреНрд╖рд╛ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░ рд╕рдХрддреА (рдХрдВрдЯреЗрдирд░ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рдмрд╛рд╣рд░), рдЕрд░реНрдерд╛рддреН, рд▓реЙрдХ-рдлреНрд░реА рдХрдВрдЯреЗрдирд░ рдХреЗ рддрддреНрд╡реЛрдВ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐рдпреЛрдВ рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХреЛ рдпреБрдЧ рдЖрдзрд╛рд░рд┐рдд рдпреЛрдЬрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдпреЛрдЬрдирд╛ рдХрд╛ рдиреБрдХрд╕рд╛рди рдпрд╣ рд╣реИ рдХрд┐ рд╕рднреА рдХрд╛рд░реНрдпрдХреНрд░рдо рдкреНрд░рд╡рд╛рд╣ рдЕрдЧрд▓реЗ рдпреБрдЧ рдореЗрдВ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рддреН, рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓реЙрдХ-рдореБрдХреНрдд рдХрдВрдЯреЗрдирд░ рдХреА рдУрд░ рдореБрдбрд╝реЗрдВ; рдпрджрд┐ рдХрдо рд╕реЗ рдХрдо рдПрдХ рдзрд╛рдЧрд╛ рдЕрдЧрд▓реЗ рдпреБрдЧ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд▓рдВрдмрд┐рдд рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЛ рд╣рдЯрд╛рдирд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдпрджрд┐ рдзрд╛рд░рд╛рдУрдВ рдХреА рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╕рдорд╛рди рдирд╣реАрдВ рд╣реИ, рддреЛ рдирд┐рдореНрди-рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╡рд╛рд▓реА рдзрд╛рд░рд╛рдПрдБ рдЙрдЪреНрдЪ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╡рд╛рд▓реА рдзрд╛рд░рд╛рдУрдВ рдХреЗ рддрддреНрд╡реЛрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╕реНрдердЧрд┐рдд рд▓реЛрдЧреЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рд╡реГрджреНрдзрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддреА рд╣реИрдВред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдПрдХ рдпреБрдЧ-рдЖрдзрд╛рд░рд┐рдд рдпреЛрдЬрдирд╛ рдХрд╛ рдиреЗрддреГрддреНрд╡ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдФрд░ рдПрдХ рдзрд╛рдЧреЗ рдХреЗ рджреБрд░реНрдШрдЯрдирд╛рдЧреНрд░рд╕реНрдд рд╣реЛрдиреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдиреЗрддреГрддреНрд╡ рдХрд░реЗрдЧрд╛) рдЕрд╕реАрдорд┐рдд рд╕реНрдореГрддрд┐ рдЦрдкрдд рдХреЗ рд▓рд┐рдПред

Libcds рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдпреБрдЧ-рдЖрдзрд╛рд░рд┐рдд рдпреЛрдЬрдирд╛ рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдХрд╛рд░рдг: рдореИрдВ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реНрдпрд╛рдкреНрдд рдкреНрд░рднрд╛рд╡реА рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рдерд╛ рдХрд┐ рдХреНрдпрд╛ рд╕рднреА рдкреНрд░рд╡рд╛рд╣ рд╡реИрд╢реНрд╡рд┐рдХ рдпреБрдЧ рдореЗрдВ рдкрд╣реБрдВрдЪреЗред рд╢рд╛рдпрдж рдкрд╛рдардХреЛрдВ рдореЗрдВ рд╕реЗ рдХреЛрдИ рдПрдХ рд╕рдорд╛рдзрд╛рди рд╕реБрдЭрд╛рдПрдЧрд╛?


рдЦрддрд░рд╛ рд╕реВрдЪрдХ



рдЗрд╕ рдпреЛрдЬрдирд╛ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдорд╛рдЗрдХрд▓ [Mic02a, Mic03] рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рд╕реНрдерд╛рдиреАрдп рд▓рд┐рдВрдХ рдХреЛ рд▓реЙрдХ-рдлреНрд░реА рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рддрддреНрд╡реЛрдВ рд╕реЗ рдмрдЪрд╛рдирд╛ рд╣реИред рд╢рд╛рдпрдж рдпрд╣ рд╕реНрдердЧрд┐рдд рд╣рдЯрд╛рдиреЗ рдХреА рд╕рдмрд╕реЗ рдкреНрд░рд╕рд┐рджреНрдз рдФрд░ рд╡рд┐рд╕реНрддреГрдд рдпреЛрдЬрдирд╛ рд╣реИред рдпрд╣ рдХреЗрд╡рд▓ рдкрд░рдорд╛рдгреБ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ рдФрд░ рдХреИрд╕ рдХреА рддрд░рд╣ "рднрд╛рд░реА" рддреБрд▓реНрдпрдХрд╛рд▓рди рдЖрджрд┐рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред
рдпреЛрдЬрдирд╛ рдХреА рдЖрдзрд╛рд░рд╢рд┐рд▓рд╛ рдпрд╣ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓реЙрдХ-рдлрд╝реНрд░реА рдСрдкрд░реЗрд╢рди рдХреЗ рдЕрдВрджрд░ рдХрдВрдЯреЗрдирд░ рдХреЛ рд▓реЙрдХ-рдлреНрд░реА рдПрд▓рд┐рдореЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдЦрд╝рддрд░рд╛ (рдЦрд╝рддрд░рдирд╛рдХ) рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдмрд╛рдзреНрдпрддрд╛ рд╣реИ, рдпрд╛рдиреА рдПрд▓реАрдореЗрдВрдЯ рдХреЗ рд╕рд╛рде рдПрд▓рд┐рдореЗрдВрдЯ рдХреЛ рдХрд╛рдо рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдЗрд╕реЗ рд╡рд░реНрддрдорд╛рди рд╕реНрдЯреНрд░реАрдо рдХреЗ рдЦрддрд░реЛрдВ рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЗ HP рд╕рд░рдгреА рдореЗрдВ рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ред HP рд╕рд░рдгреА рд╕реНрдЯреНрд░реАрдо рдХреЗ рд▓рд┐рдП рдирд┐рдЬреА рд╣реИ: рдХреЗрд╡рд▓ рд╕реНрд╡рд╛рдореА рд╕реНрдЯреНрд░реАрдо рдЗрд╕реЗ рд▓рд┐рдЦрддрд╛ рд╣реИ, рд╕рднреА рд╕реНрдЯреНрд░реАрдо рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ ( Scan рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ)ред рдпрджрд┐ рдЖрдк рд╡рд┐рднрд┐рдиреНрди рд▓реЙрдХ-рдлреНрд░реА рдХрдВрдЯреЗрдирд░реЛрдВ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рд╕рд╛рд╡рдзрд╛рдиреАрдкреВрд░реНрд╡рдХ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдзреНрдпрд╛рди рджреЗрдВрдЧреЗ рдХрд┐ HP рд╕рд░рдгреА (рдкреНрд░рддрд┐ рдереНрд░реЗрдб рдмрд┐рдВрджреБрдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛) рдХрд╛ рдЖрдХрд╛рд░ 3 - 4 рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ, рддрд╛рдХрд┐ рд╕рд░реНрдХрд┐рдЯ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдУрд╡рд░рд╣реЗрдб рдЫреЛрдЯрд╛ рд╣реЛред
рд╡рд┐рд╢рд╛рд▓ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдБ
рдирд┐рд╖реНрдкрдХреНрд╖рддрд╛ рдореЗрдВ, рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ 64 рд╕реЗ рдЕрдзрд┐рдХ рдЦрддрд░рдирд╛рдХ рдмрд┐рдВрджреБрдУрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╡рд╛рд▓реЗ "рд╡рд┐рд╢рд╛рд▓" рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдПрдВ рд╣реИрдВред рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╕реНрдХрд┐рдк-рд▓рд┐рд╕реНрдЯ рд╣реИ ( cds::container::SkipListMap ) - рдПрдХ рд╕рдВрднрд╛рд╡реНрдп рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕реВрдЪреА рдХреА рдПрдХ рд╕реВрдЪреА, рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рдПрдХ рдЪрд░ рдКрдВрдЪрд╛рдИ рдХреЗ рд╕рд╛рдеред рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрдВрдЯреЗрдирд░ рд╣рдЬрд╛рд░реНрдб рдкреЙрдЗрдВрдЯрд░ рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреБрдХреНрдд рдирд╣реАрдВ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ libcds рдореЗрдВ рдЗрд╕ рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдХрд┐рдк-рд╕реВрдЪреА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред


рдЦрддрд░рд╛ рд╕реВрдЪрдХ рдЫрджреНрдо рдХреЛрдб [Mic02]:
 //  // P :   // K :  hazard pointer    // N :   hazard pointers = K*P // R : batch size, RN=╬й(N), , R=2*N // Per-thread : //  Hazard Pouinter  //     - //    void * HP[K] //   dlist ( 0..R) unsigned dcount = 0; //      void* dlist[R]; //   //     dlist void RetireNode( void * node ) { dlist[dcount++] = node; //    тАУ    Scan if (dcount == R) Scan(); } //   //     dlist,    //  Hazard Pointer void Scan() { unsigned i; unsigned p=0; unsigned new_dcount = 0; // 0 .. N void * hptr, plist[N], new_dlist[N]; // Stage 1 тАУ    HP   //    plist   for (unsigned t=0; t < P; ++t) { void ** pHPThread = get_thread_data(t)->HP ; for (i = 0; i < K; ++i) { hptr = pHPThread[i]; if ( hptr != nullptr ) plist[p++] = hptr; } } // Stage 2 тАУ  hazard pointer' //       sort(plist); // Stage 3 тАУ  ,    hazard for ( i = 0; i < R; ++i ) { //  dlist[i]    plist  Hazard Pointer' //  dlist[i]    if ( binary_search(dlist[i], plist)) new_dlist[new_dcount++] = dlist[i]; else free(dlist[i]); } // Stage 4 тАУ     . for (i = 0; i < new_dcount; ++i ) dlist[i] = new_dlist[i]; dcount = new_dcount; } 


рдЬрдм pNode рд▓реЙрдХ-рдлреНрд░реА рдХрдВрдЯреЗрдирд░ рддрддреНрд╡ рдХреЗ RetireNode(pNode) рдХреЛ рд╣рдЯрд╛ рд░рд╣реЗ рд╣реИрдВ, рддреЛ j dlist рд▓рдВрдмрд┐рдд (рдЖрд╡рд╢реНрдпрдХ рдирд┐рд╖реНрдХрд╛рд╕рди) рддрддреНрд╡реЛрдВ рдХреА рд╕реВрдЪреА рдХреЗ рд▓рд┐рдП dlist рдХреЛ рд╕реНрдерд╛рдиреАрдп (рд╕реНрдЯреНрд░реАрдо j ) рдореЗрдВ рд╕реВрдЪреАрдмрджреНрдз рдХрд░реЗрдВред рдЬреИрд╕реЗ рд╣реА dlist рдХрд╛ рдЖрдХрд╛рд░ R рддрдХ рдкрд╣реБрдБрдЪрддрд╛ рд╣реИ ( R, N = P*K рдмрд░рд╛рдмрд░ рд╣реИ, рд▓реЗрдХрд┐рди dlist рд╕реЗ рдЕрдзрд┐рдХ рд╣реИ; рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, R = 2N ), Scan() рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд▓рдВрдмрд┐рдд рд╡рд╕реНрддреБрдУрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рд▓рдЧреА рд╣реБрдИ рд╣реИред рд╢рд░реНрдд R > P*K рдЖрд╡рд╢реНрдпрдХ рд╣реИ: рдХреЗрд╡рд▓ рдЕрдЧрд░ рдпрд╣ рд╢рд░реНрдд рдкреВрд░реА рд╣реЛрддреА рд╣реИ, рддреЛ рдпрд╣ рдЧрд╛рд░рдВрдЯреА рд╣реИ рдХрд┐ Scan() рд▓рдВрдмрд┐рдд рдбреЗрдЯрд╛ рд╕рд░рдгреА рд╕реЗ рдХреБрдЫ рднреА рдирд┐рдХрд╛рд▓рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдЧрд╛ред рдпрджрд┐ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ Scan() рд╕рд░рдгреА рд╕реЗ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣рдЯрд╛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рд╣рдореЗрдВ рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рддреНрд░реБрдЯрд┐ рдорд┐рд▓реЗрдЧреА - рд╕рд░рдгреА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рднрд░реА рд╣реБрдИ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХрд╛ рдЖрдХрд╛рд░ рдХрдо рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

Scan() рдореЗрдВ рдЪрд╛рд░ рдЪрд░рдг рд╣реЛрддреЗ рд╣реИрдВред


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 Pointer
Lock-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. HP тАУ thread-private  HP[0] = t; //  ,  m_Tail  ! if (t != m_Tail.load(std::memory_order_acquire) continue; node * next = t->next.load(std::memory_order_acquire); if (t != m_Tail) continue; if (next != nullptr) { // m_Tail     //  m_Tail m_Tail.compare_exchange_weak( t, next, std::memory_order_release); continue; } node * tmp = nullptr; if ( t->next.compare_exchange_strong( tmp, pNew, std::memory_order_release)) break; } m_Tail.compare_exchange_strong( t, pNew, std::memory_order_acq_rel ); HP[0] = nullptr; //  hazard pointer } bool dequeue(T& dest) { while true { node * h = m_Head.load(std::memory_order_relaxed); //  Hazard Pointer HP[0] = h; // ,  m_Head   if (h != m_Head.load(std::memory_order_acquire)) continue; node * t = m_Tail.load(std::memory_order_relaxed); node * next = h->next.load(std::memory_order_acquire); // head->next    Hazard Pointer HP[1] = next; //  m_Head  тАУ    if (h != m_Head.load(std::memory_order_relaxed)) continue; if (next == nullptr) { //   HP[0] = nullptr; return false; } if (h == t) { //   enqueue тАУ  m_Tail m_Tail.compare_exchange_strong( t, next, std::memory_order_release); continue; } dest = next->data; if ( m_Head.compare_exchange_strong(h, next, std::memory_order_release)) break; } //  Hazard Pointers HP[0] = nullptr; HP[1] = nullptr; //       //    . RetireNode(h); } }; 



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:


libcds HP- :

┬л┬╗ , , , ? : (, retired) :
 struct retired_ptr { typedef void (* fnDisposer )( void * ); void * ptr ; //   fnDisposer pDisposer; // - retired_ptr( void * p, fnDisposer d): ptr(p), pDisposer(d) {} }; 

( 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 ) { //  p   arrRetired     // ,  arrRetired тАУ    arrRetired.push( retired_ptr( p, make_disposer<T>::dispose )); //    тАУ  scan if ( arrRetired.full() ) scan(); } 

, , , .


HP- libcds, main() cds::gc::HP , , HP-, . , , cds::gc::HP . API HP-.

API cds::gc::HP
cds::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; } }; //   myDisposer    Foo Foo * p = new Foo ; cds::gc::HP::retire<fooDisposer>( p ); 

  •  static void force_dispose(); 

    Scan() Hazard Pointer. , , libcds .

, cds::gc::HP :
  • thread_gc тАУ (thread data), Hazard Pointer. , HP- , ,
  • Guard тАУ hazard pointer
  • template <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]); //  HP if (node1 != NULL and !is_deleted( node1 )) { node2 = DeRefLink(node1->link[x]); //  HP //  ,       //    node1 CompareAndSwapRef(&pNode->link[x],node1,node2); ReleaseRef(node2); //  HP ReleaseRef(node1); //  HP goto retry; //       ,   } ReleaseRef(node1); //  HP } } 

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- libcds
UPD (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'.

libcds
UPD (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


рд▓реЙрдХ-рдлреНрд░реА рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░рдХреНрдЪрд░реНрд╕
рд╢реБрд░реБрдЖрдд
рдореВрд▓ рдмрд╛рддреЗрдВ:

рдЕрдВрджрд░:

рдмрд╛рд╣рд░ рд╕реЗ:

Source: https://habr.com/ru/post/In202190/


All Articles