123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- #pragma once
- #include <windows.h>
- /* lock free stack object
- multiple threads can push and pop without locking
- note that order is not guaranteed. that is, if Thread 1 calls Insert before Thread 2, Thread 2's item might still make it in before.
- since it uses malloc/free for the linked list nodes, it might not be considered truely lock-free.
- use LockFreeStack2 if you can assure that you have a 'next' pointer in your class/struct
- */
- template <class value_t>
- class LockFreeStackNode
- {
- public:
- LockFreeStackNode(value_t _data)
- {
- data = _data;
- next = 0;
- }
- value_t data;
- LockFreeStackNode *next;
- };
- template <class value_t>
- class LockFreeStack
- {
- public:
- LockFreeStack()
- {
- head = 0;
- }
- void push(value_t data)
- {
- LockFreeStackNode<value_t> *new_head = new LockFreeStackNode<value_t>(data);
- LockFreeStackNode<value_t> *old_head = 0;
- do
- {
- old_head = (LockFreeStackNode<value_t> *)head;
- new_head->next = old_head;
- } while (InterlockedCompareExchangePointer((volatile PVOID *)&head, new_head, old_head) != old_head);
- }
- value_t pop()
- {
- LockFreeStackNode<value_t> *new_head = 0, *old_head = 0;
- do
- {
- old_head = (LockFreeStackNode<value_t> *)head;
- if (old_head)
- {
- new_head = old_head->next;
- }
- else
- {
- new_head = 0;
- }
- } while (InterlockedCompareExchangePointer((volatile PVOID *)&head, new_head, old_head) != old_head);
- value_t ret = old_head?old_head->data:0;
- delete old_head;
- return ret;
- }
- bool pop_ref(value_t *val)
- {
- LockFreeStackNode<value_t> *new_head = 0, *old_head = 0;
- do
- {
- old_head = (LockFreeStackNode<value_t> *)head;
- if (old_head)
- {
- new_head = old_head->next;
- }
- else
- {
- new_head = 0;
- }
- } while (InterlockedCompareExchangePointer((volatile PVOID *)&head, new_head, old_head) != old_head);
- if (old_head)
- {
- *val = old_head->data;
- delete old_head;
- return true;
- }
- return false;
- }
- volatile LockFreeStackNode<value_t> *head;
- };
- template <class value_t>
- class LockFreeStack2
- {
- public:
- LockFreeStack()
- {
- head = 0;
- }
- void push(value_t *data)
- {
- value_t *old_head = 0;
- do
- {
- old_head = head;
- data->next = old_head;
- } while (InterlockedCompareExchangePointer((volatile PVOID *)&head, data, old_head) != old_head);
- }
- value_t *pop()
- {
- value_t *new_head = 0, *old_head = 0;
- do
- {
- old_head = head;
- if (old_head)
- {
- new_head = old_head->next;
- }
- else
- {
- new_head = 0;
- }
- } while (InterlockedCompareExchangePointer((volatile PVOID *)&head, new_head, old_head) != old_head);
- return old_head;
- }
- bool pop_ref(value_t **val)
- {
- value_t *new_head = 0, *old_head = 0;
- do
- {
- old_head = head;
- if (old_head)
- {
- new_head = old_head->next;
- }
- else
- {
- new_head = 0;
- }
- } while (InterlockedCompareExchangePointer((volatile PVOID *)&head, new_head, old_head) != old_head);
- if (old_head)
- {
- *val = old_head;
- return true;
- }
- return false;
- }
- volatile value_t *head;
- };
|