#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 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 next_; rl::var data_; }; std::atomic head_; stack(stack const&); stack& operator = (stack const&); }; struct stack_test : rl::test_suite { stack s_; int produced_count_; int consumed_count_; void before() { produced_count_ = 0; consumed_count_ = 0; } void after() { typedef rl::test_suite 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(); }