introduction to lock free programming
play

Introduction to Lock-Free Programming Olivier Goffart 2014 About - PowerPoint PPT Presentation

Introduction to Lock-Free Programming Olivier Goffart 2014 About Me QStyleSheetStyle Itemviews Animation Framework QtScript (porting to JSC and V8) QObject, moc QML Debugger Modularisation . . . About Me Offering Qt help and services:


  1. Introduction to Lock-Free Programming Olivier Goffart 2014

  2. About Me QStyleSheetStyle Itemviews Animation Framework QtScript (porting to JSC and V8) QObject, moc QML Debugger Modularisation . . .

  3. About Me Offering Qt help and services: Visit http://woboq.com C++ Code browser: http://code.woboq.org

  4. Goal of this presentation Introduction to Lock-Free programming

  5. Singleton class MySingleton { 1 static MySingleton *s_instance ; 2 static QMutex s_mutex; 3 4 public: 5 6 static MySingleton *instance () 7 { 8 QMutexLocker lock (& s_mutex ); 9 if (! s_instance ) { 10 s_instance = new MySingleton (); 11 } 12 return s_instance ; 13 } 14 15 // .... 16 }; 17

  6. Singleton (wrong) static MySingleton *instance () 1 { 2 if (! s_instance ) { 3 QMutexLocker lock (& s_mutex ); 4 if (! s_instance ) { 5 s_instance = new MySingleton (); 6 } 7 } 8 return s_instance ; 9 } 10

  7. Computer architecture Compiler re-order CPU out of order execution Caches, Write buffers

  8. Singleton (Better) class MySingleton { 1 static QAtomicPointer <MySingleton > s_instance; 2 static QMutex s_mutex; 3 public: 4 static MySingleton *instance () 5 { 6 MySingleton *inst = s_instance . loadAcquire (); 7 if (! inst) { 8 QMutexLocker lck (& s_mutex ); 9 if (! s_instance .load ()) { // relaxed 10 inst = new MySingleton (); 11 s_instance . storeRelease (inst ); 12 } 13 } 14 return inst; 15 } 16 }; 17

  9. Singleton (Best) static MySingleton *instance () 1 { 2 static MySingleton inst; 3 return &inst; 4 } 5

  10. Singleton (Best) static MySingleton *instance () 1 { 2 static MySingleton inst; 3 return &inst; 4 } 5 See also: Q GLOBAL STATIC

  11. C++11 Memory model C++98 No mentions of threads. The compiler is allowed to do any optimisation that is consistant to a single thread.

  12. C++11 Memory model C++98 No mentions of threads. The compiler is allowed to do any optimisation that is consistant to a single thread. C++11 Defines race condition Restricts what kind of optimisation the compiler is allowed to do in regards to threading. std::atomic , std::thread , std::mutex

  13. C++11 Memory model C++11 § 1.10 21. The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other. Any such data race results in undefined behavior.

  14. Lock-Free programming

  15. What’s wrong with mutexes?

  16. What’s wrong with mutexes? All threads have to wait if a thread holding a lock is descheduled. More context switches waste CPU time. For real-time applications: priority inversion, unsafe in interrupts handlers, convoying.

  17. Lock-free algorithms Sometimes faster No risks of deadlock, even if a thread is terminated/killed More difficult to design and understand

  18. Lock-free algorithms Sometimes faster No risks of deadlock, even if a thread is terminated/killed More difficult to design and understand, but also fun

  19. QAtomicInt/QAtomicPointer Memory Ordering API Ordered testAndSet Acquire fetchAndStore Release fetchAndAdd Relaxed Mix and Match bool QAtomicInt :: testAndSetAcquire (int expectedValue , 1 int newValue) 2 int QAtomicInt :: fetchAndAddOrdered (int valueToAdd ) 3 T *QAtomicPointer <T >:: fetchAndStoreRelaxed (T *newValue) 4

  20. Fetch and Store T *QAtomicPointer <T >:: fetchAndStore ...(T *newValue) 1 { 2 T *oldValue = _q_value; 3 _q_value = newValue; 4 return oldValue; 5 } 6

  21. Fetch and Add int QAtomicInt :: fetchAndAdd ...( int valueToAdd ) 1 { 2 int oldValue = _q_value; 3 _q_value += valueToAdd ; 4 return oldValue; 5 } 6

  22. Test and Set bool QAtomicInt :: testAndSet ...( int expectedValue , 1 int newValue) 2 { 3 if (_q_value != expectedValue ) 4 return false; 5 _q_value = newValue; 6 return true; 7 } 8

  23. Memory ordering Acquire Release Memory access following the atomic Memory access before the atomic operation may not be re-ordered operation may not be re-ordered before that operation. after that operation. Ordered Relaxed Same Acquire and Release Operations may be re-ordered combined: operations may not be before or after. re-ordered

  24. Singleton (Lock-free) class MySingleton { 1 static QAtomicPointer <MySingleton > s_instance; 2 3 public: 4 static MySingleton *instance () 5 { 6 MySingleton *inst = s_instance . loadAcquire (); 7 if (! inst) { 8 inst = new MySingleton (); 9 if (! s_instance . testAndSetRelease (0, inst )) { 10 delete inst; 11 inst = s_instance. loadAcquire (); 12 } 13 } 14 return inst; 15 } 16 }; 17

  25. Lock-Free Stack

  26. Lock-Free Stack (Push)

  27. Lock-Free Stack (Push)

  28. Lock-Free Stack (Push)

  29. Lock-Free Stack (Push)

  30. Lock-Free Stack (Push)

  31. Lock-Free Stack (Push)

  32. Lock-free stack struct Stack { 1 QAtomicPointer <Node > head; 2 void push(Node *n) { 3 do { 4 n->next = head. loadAcquire (); 5 } while (! head. testAndSetOrdered (n->next , n)); 6 } 7 // ... 8 }; 9

  33. Lock-Free Stack (Pop)

  34. Lock-Free Stack (Pop)

  35. Lock-free stack Pop (wrong) struct Stack { 1 QAtomicPointer <Node > head; 2 // ... 3 Node *pop () { 4 Node *n; 5 do { 6 n = head. loadAcquire (); 7 } while(n && !head. testAndSetOrdered (n, n->next )); 8 return n; 9 } 10 }; 11

  36. ABA Problem

  37. ABA Problem Solutions

  38. ABA Problem Solutions Add a serial number Multiple words compare and swap Garbage collector / Reference count Hazard pointers

  39. Example in Qt Reference counting QMutex Q GLOBAL STATIC Allocation of timer ids . . .

  40. Other examples RCU (Read-copy-update) Multiple words compare and swap. Transactional memory

  41. Transactional memory In the Future... (N3718) : void push(Node *n) { 1 transaction_atomic { 2 n->next = head; 3 head = n; 4 } 5 } 6 7 Node *pop () { 8 Node *n; 9 transaction_atomic { 10 n = head; 11 if (n) 12 head = n->next; 13 } 14 return n; 15 } 16

  42. Conclusion Use mutexes. Profile.

  43. The END Questions

  44. The END Questions olivier@woboq.com Visit http://woboq.com . Read More: http://woboq.com/blog/introduction-to-lockfree-programming.html , http://woboq.com/blog/internals-of-qmutex-in-qt5.html

Recommend


More recommend