1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
#include "stdafx.h"
#include "../../relacy/relacy_std.hpp"
// TEST FAILS WITH "ACCESS TO FREED MEMORY"
class stack
{
public:
stack()
: head_(0)
{
}
void push(int data)
{
rl::var<node*> n = new node ();
n($)->data_($) = data;
node* next = head_.load(rl::memory_order_relaxed);
for (;;)
{
n($)->next_.store(next, rl::memory_order_relaxed);
if (head_.compare_exchange_weak(next, n($), rl::memory_order_release))
break;
}
}
int pop()
{
node* n = head_.load(rl::memory_order_relaxed);
for (;;)
{
if (0 == n)
break;
node* next = n->next_.load(rl::memory_order_relaxed);
if (head_.compare_exchange_weak(n, next, rl::memory_order_acquire))
break;
}
if (n)
{
int data = n->data_($);
delete n;
return data;
}
else
{
return 0;
}
}
private:
struct node
{
std::atomic<node*> next_;
rl::var<int> data_;
};
std::atomic<node*> head_;
stack(stack const&);
stack& operator = (stack const&);
};
struct stack_test : rl::test_suite<stack_test, 4>
{
stack s_;
int produced_count_;
int consumed_count_;
void before()
{
produced_count_ = 0;
consumed_count_ = 0;
}
void after()
{
typedef rl::test_suite<stack_test, 4> base_t;
RL_ASSERT(base_t::params::thread_count == produced_count_);
RL_ASSERT(base_t::params::thread_count == consumed_count_);
}
void thread(unsigned /*index*/)
{
s_.push(rand() + 1);
produced_count_ += 1;
int data = s_.pop();
RL_ASSERT(data);
consumed_count_ += 1;
}
};
int main()
{
rl::simulate<stack_test>();
}
|