F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
PriorityBufferQueue.cpp
Go to the documentation of this file.
1 // ======================================================================
2 // \title PriorityBufferQueue.hpp
3 // \author dinkel
4 // \brief An implementation of BufferQueue which uses a stable max heap
5 // data structure for the queue. Items of highest priority will
6 // be popped off of the queue first. Items of equal priority will
7 // be popped off the queue in FIFO order.
8 //
9 // \copyright
10 // Copyright 2009-2015, by the California Institute of Technology.
11 // ALL RIGHTS RESERVED. United States Government Sponsorship
12 // acknowledged.
13 //
14 // ======================================================================
15 
18 #include <Fw/Types/Assert.hpp>
19 #include <cstring>
20 #include <cstdio>
21 #include <new>
22 
23 // This is a priority queue implementation implemented using a stable max heap.
24 // Elements pushed onto the queue will be popped off in priority order.
25 // Elements of the same priority will be popped off in FIFO order.
26 namespace Os {
27 
29  // Queue handler:
31 
32  struct PriorityQueue {
34  U8* data;
38  };
39 
41  // Helper functions:
43 
45  NATIVE_UINT_TYPE* indexes = pQueue->indexes;
46 
47  // Get an available index from the index pool:
48  NATIVE_UINT_TYPE index = indexes[pQueue->startIndex % depth];
49  ++pQueue->startIndex;
50  NATIVE_UINT_TYPE diff = pQueue->stopIndex - pQueue->startIndex;
51  FW_ASSERT(
52  diff <= depth,
53  static_cast<FwAssertArgType>(diff),
54  static_cast<FwAssertArgType>(depth),
55  static_cast<FwAssertArgType>(pQueue->stopIndex),
56  static_cast<FwAssertArgType>(pQueue->startIndex));
57  return index;
58  }
59 
61  NATIVE_UINT_TYPE* indexes = pQueue->indexes;
62 
63  // Return the index back to the index pool:
64  indexes[pQueue->stopIndex % depth] = index;
65  ++pQueue->stopIndex;
66  NATIVE_UINT_TYPE diff = pQueue->stopIndex - pQueue->startIndex;
67  FW_ASSERT(
68  diff <= depth,
69  static_cast<FwAssertArgType>(diff),
70  static_cast<FwAssertArgType>(depth),
71  static_cast<FwAssertArgType>(pQueue->stopIndex),
72  static_cast<FwAssertArgType>(pQueue->startIndex));
73  }
74 
76  // Class functions:
78 
79  bool BufferQueue::initialize(NATIVE_UINT_TYPE depth, NATIVE_UINT_TYPE msgSize) {
80  // Create the priority queue data structure on the heap:
81  MaxHeap* heap = new(std::nothrow) MaxHeap;
82  if (nullptr == heap) {
83  return false;
84  }
85  if( !heap->create(depth) ) {
86  delete heap;
87  return false;
88  }
89  U8* data = new(std::nothrow) U8[depth*(sizeof(msgSize) + msgSize)];
90  if (nullptr == data) {
91  delete heap;
92  return false;
93  }
94  NATIVE_UINT_TYPE* indexes = new(std::nothrow) NATIVE_UINT_TYPE[depth];
95  if (nullptr == indexes) {
96  delete heap;
97  delete[] data;
98  return false;
99  }
100  for(NATIVE_UINT_TYPE ii = 0; ii < depth; ++ii) {
101  indexes[ii] = getBufferIndex(static_cast<NATIVE_INT_TYPE>(ii));
102  }
103  PriorityQueue* priorityQueue = new(std::nothrow) PriorityQueue;
104  if (nullptr == priorityQueue) {
105  delete heap;
106  delete[] data;
107  delete[] indexes;
108  return false;
109  }
110  priorityQueue->heap = heap;
111  priorityQueue->data = data;
112  priorityQueue->indexes = indexes;
113  priorityQueue->startIndex = 0;
114  priorityQueue->stopIndex = depth;
115  this->m_queue = priorityQueue;
116  return true;
117  }
118 
119  void BufferQueue::finalize() {
120  PriorityQueue* pQueue = static_cast<PriorityQueue*>(this->m_queue);
121  if (nullptr != pQueue)
122  {
123  MaxHeap* heap = pQueue->heap;
124  if (nullptr != heap) {
125  delete heap;
126  }
127  U8* data = pQueue->data;
128  if (nullptr != data) {
129  delete [] data;
130  }
131  NATIVE_UINT_TYPE* indexes = pQueue->indexes;
132  if (nullptr != indexes)
133  {
134  delete [] indexes;
135  }
136  delete pQueue;
137  }
138  this->m_queue = nullptr;
139  }
140 
141  bool BufferQueue::enqueue(const U8* buffer, NATIVE_UINT_TYPE size, NATIVE_INT_TYPE priority) {
142 
143  // Extract queue handle variables:
144  PriorityQueue* pQueue = static_cast<PriorityQueue*>(this->m_queue);
145  MaxHeap* heap = pQueue->heap;
146  U8* data = pQueue->data;
147 
148  // Get an available data index:
149  NATIVE_UINT_TYPE index = checkoutIndex(pQueue, this->m_depth);
150 
151  // Insert the data into the heap:
152  bool ret = heap->push(priority, index);
153  FW_ASSERT(ret, ret);
154 
155  // Store the buffer to the queue:
156  this->enqueueBuffer(buffer, size, data, index);
157 
158  return true;
159  }
160 
161  bool BufferQueue::dequeue(U8* buffer, NATIVE_UINT_TYPE& size, NATIVE_INT_TYPE &priority) {
162 
163  // Extract queue handle variables:
164  PriorityQueue* pQueue = static_cast<PriorityQueue*>(this->m_queue);
165  MaxHeap* heap = pQueue->heap;
166  U8* data = pQueue->data;
167 
168  // Get the highest priority data from the heap:
169  NATIVE_UINT_TYPE index = 0;
170  bool ret = heap->pop(priority, index);
171  FW_ASSERT(ret, ret);
172 
173  ret = this->dequeueBuffer(buffer, size, data, index);
174  if(!ret) {
175  // The dequeue failed, so push the popped
176  // value back on the heap.
177  ret = heap->push(priority, index);
178  FW_ASSERT(ret, ret);
179  return false;
180  }
181 
182  // Return the index to the available indexes:
183  returnIndex(pQueue, this->m_depth, index);
184 
185  return true;
186  }
187 }
#define FW_ASSERT(...)
Definition: Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition: BasicTypes.h:51
uint8_t U8
8-bit unsigned integer
Definition: BasicTypes.h:26
PlatformUIntType NATIVE_UINT_TYPE
Definition: BasicTypes.h:52
PlatformAssertArgType FwAssertArgType
Definition: FpConfig.h:34
A stable max heap data structure.
Definition: MaxHeap.hpp:27
void returnIndex(PriorityQueue *pQueue, NATIVE_UINT_TYPE depth, NATIVE_UINT_TYPE index)
NATIVE_UINT_TYPE checkoutIndex(PriorityQueue *pQueue, NATIVE_UINT_TYPE depth)
NATIVE_UINT_TYPE startIndex
NATIVE_UINT_TYPE * indexes
NATIVE_UINT_TYPE stopIndex