wangzhengquan
2020-07-08 3710ce88088c00599c5b108456f6dde9a4d981bc
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#ifndef __SHM_QUEUE_H__
#define __SHM_QUEUE_H__
 
#include "usg_common.h"
#include "mm.h"
#include "hashtable.h"
#include "lock_free_queue.h"
#include "logger_factory.h"
 
// default Queue size
// #define LOCK_FREE_Q_DEFAULT_SIZE 16
 
//  
 
 
template < typename ELEM_T>
class SHMQueue
{
 
private:
    static hashtable_t * getHashTable() {
        static hashtable_t *hashtable = NULL;
          
        if(hashtable == NULL) {
            int first = mm_init(sizeof(hashtable_t), (void **)&hashtable);
            if (first)
               hashtable_init(hashtable);
        }
        return hashtable;
        
    }
 
private:
    const int KEY;
 
public:
    /// @brief constructor of the class
    SHMQueue(int key=0, size_t qsize = LOCK_FREE_Q_DEFAULT_SIZE);
    
    /// @brief destructor of the class. 
    /// Note it is not virtual since it is not expected to inherit from this
    /// template
    ~SHMQueue();
 
    /// @brief returns the current number of items in the queue
    /// It tries to take a snapshot of the size of the queue, but in busy environments
    /// this function might return bogus values. 
    ///
    /// If a reliable queue size must be kept you might want to have a look at 
    /// the preprocessor variable in this header file called '_WITH_LOCK_FREE_Q_KEEP_REAL_SIZE'
    /// it enables a reliable size though it hits overall performance of the queue 
    /// (when the reliable size variable is on it's got an impact of about 20% in time)
    inline uint32_t size();
    
    /// @brief return true if the queue is full. False otherwise
    /// It tries to take a snapshot of the size of the queue, but in busy 
    /// environments this function might return bogus values. See help in method
    /// SHMQueue::size
    inline bool full();
 
    inline bool empty();
 
   
    inline bool push(const ELEM_T &a_data);
    inline bool push_nowait(const ELEM_T &a_data);
    inline bool push_timeout(const ELEM_T &a_data, struct timespec * timeout);
 
  
    inline bool pop(ELEM_T &a_data);
    inline bool pop_nowait(ELEM_T &a_data);
    inline bool pop_timeout(ELEM_T &a_data, struct timespec * timeout);
 
    inline ELEM_T& operator[](unsigned i);
 
protected:
    /// @brief the actual queue-> methods are forwarded into the real 
    ///        implementation
    LockFreeQueue<ELEM_T>* queue;
 
private:
    /// @brief disable copy constructor declaring it private
    SHMQueue<ELEM_T>(const SHMQueue<ELEM_T> &a_src);
};
 
 
template < typename ELEM_T >
SHMQueue<ELEM_T>::SHMQueue(int key, size_t qsize): KEY(key)
{
 
    hashtable_t *hashtable = getHashTable();
    //LockFreeQueue<int, 10000> q;
    if ((queue = (LockFreeQueue<ELEM_T> *)hashtable_get(hashtable, key)) == NULL ) {
        queue = new LockFreeQueue<ELEM_T>(qsize);
        hashtable_put(hashtable,  key, (void *)queue);
    }
    queue->reference++;
    LoggerFactory::getLogger().debug("SHMQueue constructor reference===%d", queue->reference.load());
}
 
template < typename ELEM_T >
SHMQueue<ELEM_T>::~SHMQueue()
{
    queue->reference--;
    LoggerFactory::getLogger().debug("SHMQueue destructor  reference===%d", queue->reference.load());
    if(queue->reference == 0) {
        delete queue;
        hashtable_t *hashtable = getHashTable();
        hashtable_remove(hashtable, KEY);
    }
}
 
template < typename ELEM_T >
inline uint32_t SHMQueue<ELEM_T>::size()
{
    return queue->size();
}  
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::full()
{
    return queue->full();
}
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::empty()
{
    return queue->empty();
}  
 
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::push(const ELEM_T &a_data)
{
   return queue->push(a_data);
    
}
 
template <
    typename ELEM_T >
inline bool SHMQueue<ELEM_T>::push_nowait(const ELEM_T &a_data)
{
   return queue->push_nowait(a_data);
    
}
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::push_timeout(const ELEM_T &a_data, struct timespec * timeout)
{
 
    return queue->push_timeout(a_data, timeout);
    
}
 
 
 
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::pop(ELEM_T &a_data)
{
   return queue->pop(a_data);
    
}
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::pop_nowait(ELEM_T &a_data)
{
    return queue->pop_nowait(a_data);
    
}
 
 
template < typename ELEM_T >
inline bool SHMQueue<ELEM_T>::pop_timeout(ELEM_T &a_data, struct timespec * timeout)
{
   return queue->pop_timeout(a_data, timeout);
    
}
 
template < typename ELEM_T >
inline ELEM_T& SHMQueue<ELEM_T>::operator[](unsigned i) {
     return queue->operator[](i);
}
 
 
 
#endif