В качестве тестовых экспериментов попробовал набросать реализацию
получилось вот что, но вот беда, при прогоне падает
в связи с этим вопрос это всегда так для lock free или я чего то упустил
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <process.h>
//////////////////////////////////////////////////////////////////////////
bool is_work = true;
//////////////////////////////////////////////////////////////////////////
//compare and swap
bool cas(long* v, long cv, long nv)
{
return (*v != InterlockedCompareExchange(v, nv, cv) );
}
//////////////////////////////////////////////////////////////////////////
template <class T>
class stack_lf
{
struct node
{
node* next_;
T value_;
};
volatile node* head_;
//
static node* make_empty_node()
{
node* n = new node();
n->next_ = 0;
n->value_ = 0;
return n;
}
static void destroy_node(node volatile * n)
{
n->next_ = 0; n->value_ = 0;
delete n, n = 0;
}
//
public:
stack_lf() : head_( make_empty_node() )
{
}
~stack_lf()
{
volatile node* h = head_;
while(h)
{
volatile node* n = h->next_;
destroy_node(h);
h = n;
}
}
//
void push(T v)
{
volatile node* next = make_empty_node();
next->value_ = v;
//
do { next->next_ = head_->next_; }
while( !cas( (long*)&head_->next_, (long)next->next_, (long)next ) );
}
bool pop(T& val)
{
volatile node* next = 0;
do
{
next = head_->next_;
if(next == NULL) { return false; }
}
while( !cas(((long*)(&(head_->next_))), ((long)next), ((long)(next->next_))) );
//
val = next->value_;
destroy_node(next);
return true;
}
};
//////////////////////////////////////////////////////////////////////////
unsigned __stdcall pusher_thread(void* pv)
{
stack_lf<long>* s = ( stack_lf<long>* )pv;
long v = 1000;
while( is_work )
{
printf("push value %d\n", v);
s->push(v);
++v;
}
return 0;
}
unsigned __stdcall poper_thread(void* pv)
{
stack_lf<long>* s = ( stack_lf<long>* )pv;
while( is_work )
{
long v;
if( s->pop(v) )
{
printf("[0x%x] pop value %d\n", GetCurrentThreadId(), v);
}
}
//////////////////////////////////////////////////////////////////////////
// pop all elements
long v;
while( s->pop(v) )
{
printf("[0x%x] pop value %d\n", GetCurrentThreadId(), v);
}
//////////////////////////////////////////////////////////////////////////
return 0;
}
int main()
{
stack_lf<long> s;
HANDLE hs0 = (HANDLE)_beginthreadex(NULL, 0, &pusher_thread, (void*)(&s), 0, NULL);
HANDLE hs1 = (HANDLE)_beginthreadex(NULL, 0, &pusher_thread, (void*)(&s), 0, NULL);
HANDLE hs2 = (HANDLE)_beginthreadex(NULL, 0, &poper_thread, (void*)(&s), 0, NULL);
HANDLE hs3 = (HANDLE)_beginthreadex(NULL, 0, &poper_thread, (void*)(&s), 0, NULL);
Sleep(100000);
is_work = false;
WaitForSingleObject(hs0, INFINITE);
WaitForSingleObject(hs1, INFINITE);
WaitForSingleObject(hs2, INFINITE);
WaitForSingleObject(hs3, INFINITE);
CloseHandle(hs0);
CloseHandle(hs1);
CloseHandle(hs2);
CloseHandle(hs3);
return 0;
}