#ifndef __SHM_QUEUE_H__ #define __SHM_QUEUE_H__ #include "hashtable.h" #include "lock_free_queue.h" #include "logger_factory.h" #include "sem_util.h" #include "shm_allocator.h" #include "usg_common.h" // default Queue size // #define LOCK_FREE_Q_DEFAULT_SIZE 16 template class SHMQueue { private: const int KEY; public: /// @brief constructor of the class SHMQueue(int key = 0, size_t qsize = LOCK_FREE_Q_DEFAULT_SIZE); ~SHMQueue(); void force_destroy(); inline uint32_t 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, const 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); static void remove_queues_exclude(int keys[], size_t length); static void remove_queues_include(int keys[], size_t length); static void remove_queue(int key); private: protected: /// @brief the actual queue-> methods are forwarded into the real /// implementation LockFreeQueue *queue; private: /// @brief disable copy constructor declaring it private SHMQueue(const SHMQueue &a_src); }; template void SHMQueue::remove_queues_exclude(int keys[], size_t length) { hashtable_t *hashtable = mm_get_hashtable(); std::set *keyset = hashtable_keyset(hashtable); std::set::iterator keyItr; LockFreeQueue *mqueue; bool found; for (keyItr = keyset->begin(); keyItr != keyset->end(); keyItr++) { found = false; for (size_t i = 0; i < length; i++) { if (*keyItr == keys[i]) { found = true; break; } } if (!found) { // 销毁共享内存的queue mqueue = (LockFreeQueue *)hashtable_get(hashtable, *keyItr); delete mqueue; hashtable_remove(hashtable, *keyItr); } } delete keyset; } template void SHMQueue::remove_queues_include(int keys[], size_t length) { hashtable_t *hashtable = mm_get_hashtable(); LockFreeQueue *mqueue; for(int i = 0; i< length; i++) { // 销毁共享内存的queue mqueue = (LockFreeQueue *)mm_get_by_key(keys[i]); delete mqueue; hashtable_remove(hashtable, keys[i]); } } template void SHMQueue::remove_queue(int key) { int keys[] = {key}; remove_queues_include(keys, 1); } template SHMQueue::SHMQueue(int key, size_t qsize) : KEY(key) { hashtable_t *hashtable = mm_get_hashtable(); queue = (LockFreeQueue *)hashtable_get(hashtable, key); if (queue == NULL || (void *)queue == (void *)1) { queue = new LockFreeQueue(qsize); hashtable_put(hashtable, key, (void *)queue); } queue->reference++; LoggerFactory::getLogger().debug("SHMQueue constructor reference===%d", queue->reference.load()); } template SHMQueue::~SHMQueue() { if(queue == NULL) { // queue已经销毁 return; } SemUtil::dec(queue->mutex); queue->reference--; // LoggerFactory::getLogger().debug("SHMQueue destructor reference===%d", if (queue->reference.load() == 0) { delete queue; queue = NULL; hashtable_t *hashtable = mm_get_hashtable(); hashtable_remove(hashtable, KEY); // 此时queue已经销毁,无需 SemUtil::inc(queue->mutex) // printf("SHMQueue destructor delete queue\n"); } else { SemUtil::inc(queue->mutex); } } template void SHMQueue::force_destroy() { if(queue == NULL) { // queue已经销毁 return; } SemUtil::dec(queue->mutex); delete queue; queue = NULL; hashtable_t *hashtable = mm_get_hashtable(); hashtable_remove(hashtable, KEY); // 此时queue已经销毁,无需 SemUtil::inc(queue->mutex) } template inline uint32_t SHMQueue::size() { return queue->size(); } template inline bool SHMQueue::full() { return queue->full(); } template inline bool SHMQueue::empty() { return queue->empty(); } template inline bool SHMQueue::push(const ELEM_T &a_data) { return queue->push(a_data); } template inline bool SHMQueue::push_nowait(const ELEM_T &a_data) { return queue->push_nowait(a_data); } template inline bool SHMQueue::push_timeout(const ELEM_T &a_data, const struct timespec *timeout) { return queue->push_timeout(a_data, timeout); } template inline bool SHMQueue::pop(ELEM_T &a_data) { // printf("SHMQueue pop before\n"); int rv = queue->pop(a_data); // printf("SHMQueue after before\n"); return rv; } template inline bool SHMQueue::pop_nowait(ELEM_T &a_data) { return queue->pop_nowait(a_data); } template inline bool SHMQueue::pop_timeout(ELEM_T &a_data, struct timespec *timeout) { return queue->pop_timeout(a_data, timeout); } template inline ELEM_T &SHMQueue::operator[](unsigned i) { return queue->operator[](i); } #endif