Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HeapRing.cpp Source File

HeapRing.cpp

00001 #include "HeapRing.h"
00002 
00003 #include <cstdlib>
00004 
00005 #include "cmsis.h"
00006 
00007 /*
00008  * constructors
00009  */
00010 
00011 template<class kind> HeapRing<kind>::HeapRing()
00012 {
00013     head_i = tail_i = length = 0;
00014     ring = NULL;
00015 }
00016 
00017 template<class kind> HeapRing<kind>::HeapRing(unsigned int length)
00018 {
00019     head_i = tail_i = 0;
00020     ring = new kind[length];
00021     // TODO: handle allocation failure
00022     this->length = length;
00023 }
00024 
00025 /*
00026  * destructor
00027  */
00028 
00029 template<class kind> HeapRing<kind>::~HeapRing()
00030 {
00031     head_i = tail_i = length = 0;
00032     if (ring)
00033         delete [] ring;
00034     ring = NULL;
00035 }
00036 
00037 /*
00038  * index accessors (protected)
00039  */
00040 
00041 template<class kind> unsigned int HeapRing<kind>::next(unsigned int item)
00042 {
00043     if (length == 0)
00044         return 0;
00045 
00046     if (++item >= length)
00047         return 0;
00048 
00049     return item;
00050 }
00051 
00052 template<class kind> unsigned int HeapRing<kind>::prev(unsigned int item)
00053 {
00054     if (length == 0)
00055         return 0;
00056 
00057     if (item == 0)
00058         return (length - 1);
00059     else
00060         return (item - 1);
00061 }
00062 
00063 /*
00064  * reference accessors
00065  */
00066 
00067 template<class kind> kind& HeapRing<kind>::head()
00068 {
00069     return ring[head_i];
00070 }
00071 
00072 template<class kind> kind& HeapRing<kind>::tail()
00073 {
00074     return ring[tail_i];
00075 }
00076 
00077 template<class kind> kind& HeapRing<kind>::item(unsigned int i)
00078 {
00079     return ring[i];
00080 }
00081 
00082 template<class kind> void HeapRing<kind>::push_front(kind& item)
00083 {
00084     ring[head_i] = item;
00085     head_i = next(head_i);
00086 }
00087 
00088 template<class kind> kind& HeapRing<kind>::pop_back()
00089 {
00090     kind& r = ring[tail_i];
00091     tail_i = next(tail_i);
00092     return r;
00093 }
00094 
00095 /*
00096  * pointer accessors
00097  */
00098 
00099 template<class kind> kind* HeapRing<kind>::head_ref()
00100 {
00101     return &ring[head_i];
00102 }
00103 
00104 template<class kind> kind* HeapRing<kind>::tail_ref()
00105 {
00106     return &ring[tail_i];
00107 }
00108 
00109 template<class kind> kind* HeapRing<kind>::item_ref(unsigned int i)
00110 {
00111     return &ring[i];
00112 }
00113 
00114 template<class kind> void HeapRing<kind>::produce_head()
00115 {
00116     while (is_full());
00117     head_i = next(head_i);
00118 }
00119 
00120 template<class kind> void HeapRing<kind>::consume_tail()
00121 {
00122     if (!is_empty())
00123         tail_i = next(tail_i);
00124 }
00125 
00126 /*
00127  * queue status accessors
00128  */
00129 
00130 template<class kind> bool HeapRing<kind>::is_full()
00131 {
00132     __disable_irq();
00133     bool r = (next(head_i) == tail_i);
00134     __enable_irq();
00135 
00136     return r;
00137 }
00138 
00139 template<class kind> bool HeapRing<kind>::is_empty()
00140 {
00141     __disable_irq();
00142     bool r = (head_i == tail_i);
00143     __enable_irq();
00144 
00145     return r;
00146 }
00147 
00148 /*
00149  * resize
00150  */
00151 
00152 template<class kind> bool HeapRing<kind>::resize(unsigned int length)
00153 {
00154     if (is_empty())
00155     {
00156         if (length == 0)
00157         {
00158             __disable_irq();
00159 
00160             if (is_empty()) // check again in case something was pushed
00161             {
00162                 head_i = tail_i = this->length = 0;
00163 
00164                 __enable_irq();
00165 
00166                 if (ring)
00167                     delete [] ring;
00168                 ring = NULL;
00169 
00170                 return true;
00171             }
00172 
00173             __enable_irq();
00174 
00175             return false;
00176         }
00177 
00178         // Note: we don't use realloc so we can fall back to the existing ring if allocation fails
00179         kind* newring = new kind[length];
00180 
00181         if (newring != NULL)
00182         {
00183             kind* oldring = ring;
00184 
00185             __disable_irq();
00186 
00187             if (is_empty()) // check again in case something was pushed while malloc did its thing
00188             {
00189                 ring = newring;
00190                 this->length = length;
00191                 head_i = tail_i = 0;
00192 
00193                 __enable_irq();
00194 
00195                 if (oldring)
00196                     delete [] oldring;
00197 
00198                 return true;
00199             }
00200 
00201             __enable_irq();
00202 
00203             delete [] newring;
00204         }
00205     }
00206 
00207     return false;
00208 }
00209 
00210 template<class kind> bool HeapRing<kind>::provide(kind* buffer, unsigned int length)
00211 {
00212     __disable_irq();
00213 
00214     if (is_empty())
00215     {
00216         kind* oldring = ring;
00217 
00218         if ((buffer != NULL) && (length > 0))
00219         {
00220             ring = buffer;
00221             this->length = length;
00222             head_i = tail_i = 0;
00223 
00224             __enable_irq();
00225 
00226             if (oldring)
00227                 delete [] oldring;
00228             return true;
00229         }
00230     }
00231 
00232     __enable_irq();
00233 
00234     return false;
00235 }