File: stack.cpp

package info (click to toggle)
relacy 0.0%2Bgit20191025.acc09bb-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 1,472 kB
  • sloc: cpp: 17,955; makefile: 68; ansic: 16; sh: 15
file content (105 lines) | stat: -rw-r--r-- 2,035 bytes parent folder | download
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>();
}