| | |
| | | // queue.h -- interface for a queue |
| | | #ifndef SAbstractQueue_H_ |
| | | #define SAbstractQueue_H_ |
| | | #include "mm.h" |
| | | #include "pcsem.h" |
| | | |
| | | template <typename T> |
| | | class SAbstractQueue |
| | |
| | | #ifndef SLinkedLockFreeQueue_H_ |
| | | #define SLinkedLockFreeQueue_H_ |
| | | #include "mm.h" |
| | | #include "pcsem.h" |
| | | #include "sem_util.h" |
| | | #include "SAbstractQueue.h" |
| | | |
| | | |
| | |
| | | Head.store(pointer, std::memory_order_relaxed); |
| | | Tail.store(pointer, std::memory_order_relaxed); |
| | | |
| | | slots = pcsem::init(IPC_PRIVATE, qsize); |
| | | items = pcsem::init(IPC_PRIVATE, 0); |
| | | slots = SemUtil::get(IPC_PRIVATE, qsize); |
| | | items = SemUtil::get(IPC_PRIVATE, 0); |
| | | |
| | | } |
| | | |
| | |
| | | SLinkedLockFreeQueue<T>::~SLinkedLockFreeQueue() |
| | | { |
| | | std::cerr << "SLinkedLockFreeQueue destory" << std::endl; |
| | | pcsem::remove(slots); |
| | | pcsem::remove(items); |
| | | SemUtil::remove(slots); |
| | | SemUtil::remove(items); |
| | | |
| | | |
| | | Node<T> * nodeptr; |
| | |
| | | template <typename T> |
| | | bool SLinkedLockFreeQueue<T>::add(const T & item) |
| | | { |
| | | if (pcsem::dec(slots) == -1) { |
| | | if (SemUtil::dec(slots) == -1) { |
| | | err_exit(errno, "add"); |
| | | } |
| | | |
| | | if (SLinkedLockFreeQueue<T>::_add(item)) { |
| | | pcsem::inc(items); |
| | | SemUtil::inc(items); |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | template <typename T> |
| | | bool SLinkedLockFreeQueue<T>::add_nowait(const T & item) |
| | | { |
| | | if (pcsem::dec_nowait(slots) == -1) { |
| | | if (SemUtil::dec_nowait(slots) == -1) { |
| | | if (errno == EAGAIN) |
| | | return false; |
| | | else |
| | |
| | | } |
| | | |
| | | if (SLinkedLockFreeQueue<T>::_add(item)) { |
| | | pcsem::inc(items); |
| | | SemUtil::inc(items); |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | template <typename T> |
| | | bool SLinkedLockFreeQueue<T>::add_timeout(const T & item, struct timespec * timeout) |
| | | { |
| | | if (pcsem::dec_timeout(slots, timeout) == -1) { |
| | | if (SemUtil::dec_timeout(slots, timeout) == -1) { |
| | | if (errno == EAGAIN) |
| | | return false; |
| | | else |
| | |
| | | } |
| | | |
| | | if (SLinkedLockFreeQueue<T>::_add(item)){ |
| | | pcsem::inc(items); |
| | | SemUtil::inc(items); |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | template <typename T> |
| | | bool SLinkedLockFreeQueue<T>::remove(T & item) |
| | | { |
| | | if (pcsem::dec(items) == -1) { |
| | | if (SemUtil::dec(items) == -1) { |
| | | err_exit(errno, "remove"); |
| | | } |
| | | |
| | | if (SLinkedLockFreeQueue<T>::_remove(item)) { |
| | | pcsem::inc(slots); |
| | | SemUtil::inc(slots); |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | template <typename T> |
| | | bool SLinkedLockFreeQueue<T>::remove_nowait(T & item) |
| | | { |
| | | if (pcsem::dec_nowait(items) == -1) { |
| | | if (SemUtil::dec_nowait(items) == -1) { |
| | | if (errno == EAGAIN) |
| | | return false; |
| | | else |
| | |
| | | } |
| | | |
| | | if (SLinkedLockFreeQueue<T>::_remove(item)) { |
| | | pcsem::inc(slots); |
| | | SemUtil::inc(slots); |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | template <typename T> |
| | | bool SLinkedLockFreeQueue<T>::remove_timeout(T & item, struct timespec * timeout) |
| | | { |
| | | if (pcsem::dec_timeout(items, timeout) == -1) { |
| | | if (SemUtil::dec_timeout(items, timeout) == -1) { |
| | | if (errno == EAGAIN) |
| | | return false; |
| | | else |
| | |
| | | } |
| | | |
| | | if (SLinkedLockFreeQueue<T>::_remove(item)) { |
| | | pcsem::inc(slots); |
| | | SemUtil::inc(slots); |
| | | return true; |
| | | } |
| | | return false; |
| | |
| | | /// environments this function might return bogus values. See help in method |
| | | /// LockFreeQueue::size |
| | | inline bool full(); |
| | | |
| | | inline bool empty(); |
| | | |
| | | /// @brief push an element at the tail of the queue |
| | | /// @param the element to insert in the queue |
| | |
| | | inline uint32_t size(); |
| | | |
| | | inline bool full(); |
| | | |
| | | |
| | | inline bool empty(); |
| | | |
| | | bool push(const ELEM_T &a_data); |
| | |
| | | #define __LOCK_FREE_QUEUE_IMPL_H__ |
| | | |
| | | #include <assert.h> // assert() |
| | | #include "mm.h" |
| | | #include "sem_util.h" |
| | | |
| | | template < |
| | | typename ELEM_T, |
| | |
| | | inline bool LockFreeQueue<ELEM_T, Q_TYPE>::full() |
| | | { |
| | | return m_qImpl.full(); |
| | | } |
| | | |
| | | template < |
| | | typename ELEM_T, |
| | | template <typename T> class Q_TYPE> |
| | | inline bool LockFreeQueue<ELEM_T, Q_TYPE>::empty() |
| | | { |
| | | return m_qImpl.empty(); |
| | | } |
| | | |
| | | template < |
| | |
| | | |
| | | #include <assert.h> // assert() |
| | | #include <sched.h> // sched_yield() |
| | | #include "mm.h" |
| | | #include "pcsem.h" |
| | | |
| | | template <typename ELEM_T> |
| | | int ArrayLockFreeQueueMultipleProducers<ELEM_T>::m_reference = 0; |
| | | |
| | |
| | | #include "SLinkedLockFreeQueue.h" |
| | | |
| | | namespace QueueFactory{ |
| | | hashtable_t * getHashTable() { |
| | | static hashtable_t *hashtable = NULL; |
| | | int first; |
| | | |
| | | if(hashtable == NULL) { |
| | | first = mm_init(sizeof(hashtable_t), (void **)&hashtable); |
| | | if (first) |
| | | hashtable_init(hashtable); |
| | | } |
| | | return hashtable; |
| | | |
| | | } |
| | | |
| | | template <typename T> |
| | | SLinkedLockFreeQueue<T>* createLinkedLockFreeQueue(int key, size_t size) { |
| | | hashtable_t *hashtable; |
| | | |
| | | |
| | | SLinkedLockFreeQueue<T> *queue; |
| | | int first; |
| | | |
| | | first = mm_init(sizeof(hashtable_t), (void **)&hashtable); |
| | | |
| | | if (first) |
| | | hashtable_init(hashtable); |
| | | hashtable_t *hashtable = getHashTable(); |
| | | |
| | | |
| | | if ((queue = (SLinkedLockFreeQueue<T> *)hashtable_get(hashtable, key)) == NULL ) { |
| | | queue = new SLinkedLockFreeQueue<T>(size); |
| | |
| | | |
| | | template <typename T> |
| | | LockFreeQueue<T>* createArrayLockFreeQueue(int key, size_t size=16) { |
| | | hashtable_t *hashtable; |
| | | |
| | | LockFreeQueue<T> *queue; |
| | | int first; |
| | | |
| | | first = mm_init(sizeof(hashtable_t), (void **)&hashtable); |
| | | |
| | | if (first) |
| | | hashtable_init(hashtable);; |
| | | hashtable_t *hashtable = getHashTable(); |
| | | //LockFreeQueue<int, 10000> q; |
| | | if ((queue = (LockFreeQueue<T> *)hashtable_get(hashtable, key)) == NULL ) { |
| | | queue = new LockFreeQueue<T>(size); |
| | |
| | | |
| | | |
| | | template <typename T> |
| | | LockFreeQueue<T>* createQueue(int key, size_t size) { |
| | | LockFreeQueue<T>* createQueue(int key, size_t size = 16) { |
| | | return QueueFactory::createArrayLockFreeQueue<T>(key, size); |
| | | } |
| | | |
| | | /** |
| | | * destroy queue |
| | | */ |
| | | template <typename T> |
| | | void dropQueue(int key) { |
| | | |
| | | LockFreeQueue<T> *queue = QueueFactory::createQueue<T> (key); |
| | | delete queue; |
| | | hashtable_t *hashtable = getHashTable(); |
| | | hashtable_remove(hashtable, key); |
| | | } |
| | | |
| | | } |
| | | #endif |
| | |
| | | * 管理共享内存的分配,与释放 |
| | | */ |
| | | #include "mm.h" |
| | | #include "pcsem.h" |
| | | #include "sem_util.h" |
| | | |
| | | |
| | | /* $begin mallocmacros */ |
| | |
| | | #define MIN_BLOCK_SIZE (ALIGN( (SIZE_T_SIZE << 1) + SIZE_T_SIZE + (PTR_SIZE << 1) )) |
| | | |
| | | |
| | | #define MAX(x, y) ((x) > (y)? (x) : (y)) |
| | | //#define MAX(x, y) ((x) > (y)? (x) : (y)) |
| | | |
| | | /* Pack a size and allocated bit into a word */ |
| | | #define PACK(size, alloc) ((size) | (alloc)) //line:vm:mm:pack |
| | |
| | | |
| | | static int shmid = -1; |
| | | static void *shmp; |
| | | static int mutex = pcsem::init(8899, 1); |
| | | //static int mutex = SemUtil::get(8899, 1); |
| | | static int mutex = SemUtil::get(IPC_PRIVATE, 1); |
| | | |
| | | static void *mem_start_brk; /* points to first byte of heap */ |
| | | static void *mem_brk; /* points to last byte of heap */ |
| | |
| | | |
| | | //fprintf(stderr, "mm_malloc : size=%u\n", size); |
| | | /* Search the free list for a fit */ |
| | | pcsem::dec(mutex); |
| | | SemUtil::dec(mutex); |
| | | if ((ptr = find_fit(newsize)) != NULL) |
| | | { |
| | | aptr = place(ptr, newsize); |
| | | pcsem::inc(mutex); |
| | | SemUtil::inc(mutex); |
| | | return aptr; |
| | | } else { |
| | | fprintf(stderr, "mm_malloc : out of memery\n"); |
| | |
| | | |
| | | |
| | | size_t size = GET_SIZE(HDRP(ptr)); |
| | | pcsem::dec(mutex); |
| | | SemUtil::dec(mutex); |
| | | PUT(HDRP(ptr), PACK(size, 0)); |
| | | PUT(FTRP(ptr), PACK(size, 0)); |
| | | coalesce(ptr); |
| | | pcsem::inc(mutex); |
| | | SemUtil::inc(mutex); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | |
| | | //已经初始化过了 |
| | | pcsem::dec(mutex); |
| | | SemUtil::dec(mutex); |
| | | if (shmid != -1){ |
| | | *addr = shmp; |
| | | pcsem::inc(mutex); |
| | | SemUtil::inc(mutex); |
| | | return false; |
| | | } |
| | | |
| | |
| | | |
| | | if(!first) { |
| | | *addr = shmp; |
| | | pcsem::inc(mutex); |
| | | SemUtil::inc(mutex); |
| | | return first; |
| | | } |
| | | |
| | |
| | | err_exit(errno, "mm_init extend_heap"); |
| | | |
| | | *addr = shmp; |
| | | pcsem::inc(mutex); |
| | | SemUtil::inc(mutex); |
| | | return first; |
| | | } |
| | | |
| | | |
| | | |
| | | void mm_deinit(void) { |
| | | void mm_destroy(void) { |
| | | |
| | | if (shmdt(shmp) == -1) |
| | | err_exit(errno, "mm_init shmdt"); |
| | | if (shmctl(shmid, IPC_RMID, 0) == -1) |
| | | err_exit(errno, "mm_init shmctl IPC_RMID"); |
| | | pcsem::remove(mutex); |
| | | SemUtil::remove(mutex); |
| | | } |
| | | /* |
| | | * extend_heap - Extend heap with free block and return its block pointer |
| | |
| | | #include "usg_typedef.h" |
| | | #include <sys/sem.h> |
| | | #include <sys/shm.h> |
| | | #define MAX_HEAP (20*(1<<20)) /* 20 MB */ |
| | | #define MAX_HEAP (512*(1<<20)) /* 20 MB */ |
| | | /* Hard-coded keys for IPC objects */ |
| | | |
| | | #define SHM_KEY 0x1234 /* Key for shared memory segment */ |
| | |
| | | #define OBJ_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) |
| | | |
| | | extern bool mm_init(size_t offset, void **addr); |
| | | extern void mm_deinit(void); |
| | | extern void mm_destroy(void); |
| | | extern void *mm_malloc (size_t size); |
| | | extern void mm_free (void *ptr); |
| | | extern void *mm_realloc(void *ptr, size_t size); |
File was renamed from squeue/pcsem.c |
| | |
| | | #include "pcsem.h" |
| | | #include "sem_util.h" |
| | | |
| | | |
| | | int pcsem::init(key_t key, unsigned int value) { |
| | | int SemUtil::get(key_t key, unsigned int value) { |
| | | int semid, perms; |
| | | |
| | | perms = S_IRUSR | S_IWUSR; |
| | |
| | | set to EINTR if operation was interrupted by a signal handler */ |
| | | |
| | | /* Reserve semaphore - decrement it by 1 */ |
| | | int pcsem::dec(int semId) |
| | | int SemUtil::dec(int semId) |
| | | { |
| | | struct sembuf sops; |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int pcsem::dec_nowait(int semId) |
| | | int SemUtil::dec_nowait(int semId) |
| | | { |
| | | struct sembuf sops; |
| | | |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int pcsem::dec_timeout(int semId, struct timespec * timeout) |
| | | int SemUtil::dec_timeout(int semId, struct timespec * timeout) |
| | | { |
| | | struct sembuf sops; |
| | | |
| | |
| | | |
| | | |
| | | /* Release semaphore - increment it by 1 */ |
| | | int pcsem::inc(int semId) |
| | | int SemUtil::inc(int semId) |
| | | { |
| | | struct sembuf sops; |
| | | |
| | |
| | | return semop(semId, &sops, 1); |
| | | } |
| | | |
| | | void pcsem::remove(int semid) { |
| | | void SemUtil::remove(int semid) { |
| | | union semun dummy; |
| | | if (semctl(semid, 0, IPC_RMID, dummy) == -1) |
| | | err_exit(errno, "semctl"); |
File was renamed from squeue/pcsem.h |
| | |
| | | #include "usg_common.h" |
| | | #include "usg_typedef.h" |
| | | |
| | | namespace pcsem { |
| | | namespace SemUtil { |
| | | |
| | | int init(key_t key, unsigned int value); |
| | | int get(key_t key, unsigned int value); |
| | | int dec(int semId); |
| | | int dec_nowait(int semId); |
| | | int dec_timeout(int semId, struct timespec * timeout); |
| | |
| | | }; |
| | | |
| | | // 销毁共享内存和信号 |
| | | void destroy() { |
| | | void destroy(int key) { |
| | | |
| | | LockFreeQueue<struct Item> *queue = QueueFactory::createQueue<struct Item> (1, 16); |
| | | //queue->~LockFreeQueue(); |
| | | delete queue; |
| | | mm_deinit(); |
| | | // LockFreeQueue<struct Item> *queue = QueueFactory::createQueue<struct Item> (1, 16); |
| | | // //queue->~LockFreeQueue(); |
| | | // delete queue; |
| | | |
| | | QueueFactory::dropQueue<struct Item>(key); |
| | | mm_destroy(); |
| | | |
| | | |
| | | } |
| | |
| | | int main () { |
| | | unsigned int i = 0; |
| | | |
| | | |
| | | int key = 2; |
| | | |
| | | struct Item item; |
| | | |
| | | size_t qsize = 1; |
| | | LockFreeQueue<struct Item> *queue = QueueFactory::createQueue<struct Item> (2, qsize); |
| | | size_t qsize = 16; |
| | | LockFreeQueue<struct Item> *queue = QueueFactory::createQueue<struct Item> (key, qsize); |
| | | |
| | | // LockFreeQueue<struct Item> queue(16); |
| | | for(i = 0; i < qsize; i++) { |
| | |
| | | |
| | | i = 0; |
| | | while((queue->pop(item)) ) { |
| | | cout << i << " 出队:" << item.pic << ", " << item.info << endl; |
| | | cout << i << " pop:" << item.pic << ", " << item.info << endl; |
| | | // cout << item.pic << endl; |
| | | |
| | | i++; |
| | | |
| | | } |
| | | |
| | | |
| | | destroy(); |
| | | destroy(key); |
| | | |
| | | } |