// queue.h -- interface for a queue #ifndef SQUEUE_H_ #define SQUEUE_H_ #include "common.h" #include "mm.h" #include "pcsem.h" template class Node { public: T item; Node * next; void *operator new(size_t size){ return mm_malloc(size); } void operator delete(void *p) { return mm_free(p); } }; template class SQueue { private: // class scope definitions // Node is a nested structure definition local to this class void *shmp; int first; enum {Q_SIZE = 10}; int slots; int items; // private class members Node * front; // pointer to front of Queue Node * rear; // pointer to rear of Queue size_t count; // current number of size in Queue const size_t qsize; // maximum number of size in Queue // preemptive definitions to prevent public copying SQueue(const SQueue & q) : qsize(0) { } SQueue & operator=(const SQueue & q) { return *this;} bool _enqueue(const T &item); // add item to end bool _dequeue(T &item); // remove item from front public: SQueue(size_t qs = Q_SIZE); // create queue with a qs limit ~SQueue(); bool isempty() const; bool isfull() const; int size() const; bool enqueue(const T &item); // add item to end bool enqueue_nowait(const T &item); bool enqueue_timeout(const T &item, struct timespec *timeout); bool dequeue(T &item); bool dequeue_nowait(T &item); bool dequeue_timeout(T &item, struct timespec * timeout); T& operator[](int i); }; // Queue methods template SQueue::SQueue(size_t qs) : qsize(qs) { front = rear = NULL; // or nullptr count = 0; //std::cout << "=====qsize ==" << qsize << std::endl; slots = pcsem::init(145, qsize); items = pcsem::init(146, 0); } template SQueue::~SQueue() { std::cout << "squeue destory" << std::endl; pcsem::remove(slots); pcsem::remove(items); Node * temp; while (front != NULL) // while queue is not yet empty { temp = front; // save address of front item front = front->next;// reset pointer to next item delete temp; // delete former front } } template bool SQueue::isempty() const { return count == 0; } template bool SQueue::isfull() const { return count == qsize; } template int SQueue::size() const { return count; } // Add item to queue template bool SQueue::_enqueue(const T & item) { if (isfull()) return false; Node * add = new Node; // create node // on failure, new throws std::bad_alloc exception add->item = item; // set node pointers add->next = NULL; // or nullptr; count++; if (front == NULL) // if queue is empty, front = add; // place item at front else rear->next = add; // else place at rear rear = add; return true; } template bool SQueue::enqueue(const T & item) { if (pcsem::dec(slots) == -1) { err_exit(errno, "enqueue"); } if (SQueue::_enqueue(item)) { pcsem::inc(items); return true; } return false; } template bool SQueue::enqueue_nowait(const T & item) { if (pcsem::dec_nowait(slots) == -1) { if (errno == EAGAIN) return false; else err_exit(errno, "enqueue_nowait"); } if (SQueue::_enqueue(item)) { pcsem::inc(items); return true; } return false; } template bool SQueue::enqueue_timeout(const T & item, struct timespec * timeout) { if (pcsem::dec_timeout(slots, timeout) == -1) { if (errno == EAGAIN) return false; else err_exit(errno, "enqueue_timeout"); } if (SQueue::_enqueue(item)){ pcsem::inc(items); return true; } return false; } // Place front item into item variable and remove from queue template bool SQueue::_dequeue(T & item) { if (isempty()) return false; item = front->item; // set item to first item in queue count--; Node * temp = front; // save location of first item front = front->next; // reset front to next item delete temp; // delete former first item if (count == 0) rear = NULL; return true; } template bool SQueue::dequeue(T & item) { if (pcsem::dec(items) == -1) { err_exit(errno, "dequeue"); } if (SQueue::_dequeue(item)) { pcsem::inc(slots); return true; } return false; } template bool SQueue::dequeue_nowait(T & item) { if (pcsem::dec_nowait(items) == -1) { if (errno == EAGAIN) return false; else err_exit(errno, "dequeue_nowait"); } if (SQueue::_dequeue(item)) { pcsem::inc(slots); return true; } return false; } template bool SQueue::dequeue_timeout(T & item, struct timespec * timeout) { if (pcsem::dec_timeout(items, timeout) == -1) { if (errno == EAGAIN) return false; else err_exit(errno, "dequeue_timeout"); } if (SQueue::_dequeue(item)) { pcsem::inc(slots); return true; } return false; } template T& SQueue::operator[](int i) { if (i < 0 || i >= count) { std::cerr << "Error in array limits: " << i << " is out of range\n"; std::exit(EXIT_FAILURE); } Node * temp = front; while(i-->0) { temp = temp->next; } return temp->item; } #endif