Merge pull request #110 from tesselode/fixes
[wdl/wdl-ol.git] / WDL / fastqueue.h
blobc14e62d13517c8995a10793a370000e89dbaeaee
1 /*
2 WDL - fastqueue.h
3 Copyright (C) 2006 and later Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
22 This file defines and implements a class which can queue arbitrary amounts of data.
23 It is optimized for lots of reads and writes with a significant queue (i.e. it doesnt
24 have to shuffle much memory around).
26 The downside is that you can't just ask for a pointer to specific bytes, it may have to peice
27 it together into a buffer of your choosing (or you can step through the buffers using GetPtr()).
32 #ifndef _WDL_FASTQUEUE_H_
33 #define _WDL_FASTQUEUE_H_
36 #include "ptrlist.h"
38 #define WDL_FASTQUEUE_ADD_NOZEROBUF ((void *)(INT_PTR)0xf0)
40 class WDL_FastQueue
42 struct fqBuf
44 int alloc_size;
45 int used;
46 char data[8];
48 public:
49 WDL_FastQueue(int bsize=65536-64, int maxemptieskeep=-1)
51 m_avail=0;
52 m_bsize=bsize<32?32:bsize;
53 m_offs=0;
54 m_maxemptieskeep=maxemptieskeep;
56 ~WDL_FastQueue()
58 m_queue.Empty(true,free);
59 m_empties.Empty(true,free);
62 void *Add(const void *buf, int len) // buf can be NULL to add zeroes
64 if (len < 1) return NULL;
66 fqBuf *qb=m_queue.Get(m_queue.GetSize()-1);
67 if (!qb || (qb->used + len) > qb->alloc_size)
69 const int esz=m_empties.GetSize()-1;
70 qb=m_empties.Get(esz);
71 m_empties.Delete(esz);
72 if (qb && qb->alloc_size < len) // spare buffer is not big enough, toss it
74 free(qb);
75 qb=NULL;
77 if (!qb)
79 const int sz=len < m_bsize ? m_bsize : len;
80 qb=(fqBuf *)malloc(sz + sizeof(fqBuf) - sizeof(qb->data));
81 if (!qb) return NULL;
82 qb->alloc_size = sz;
84 qb->used=0;
85 m_queue.Add(qb);
88 void *ret = qb->data + qb->used;
89 if (buf)
91 if (buf != WDL_FASTQUEUE_ADD_NOZEROBUF)
93 memcpy(ret, buf, len);
96 else
98 memset(ret, 0, len);
101 qb->used += len;
102 m_avail+=len;
103 return ret;
106 void Clear(int limitmaxempties=-1)
108 int x=m_queue.GetSize();
109 if (limitmaxempties<0) limitmaxempties = m_maxemptieskeep;
110 while (x > 0)
112 if (limitmaxempties<0 || m_empties.GetSize()<limitmaxempties)
114 m_empties.Add(m_queue.Get(--x));
116 else
118 free(m_queue.Get(--x));
120 m_queue.Delete(x);
122 m_offs=0;
123 m_avail=0;
126 void Advance(int cnt)
128 m_offs += cnt;
129 m_avail -= cnt;
130 if (m_avail<0)m_avail=0;
132 fqBuf *mq;
133 while ((mq=m_queue.Get(0)))
135 const int sz=mq->used;
136 if (m_offs < sz) break;
137 m_offs -= sz;
139 if (m_maxemptieskeep<0 || m_empties.GetSize()<m_maxemptieskeep)
141 m_empties.Add(mq);
143 else
145 free(mq);
147 m_queue.Delete(0);
149 if (!mq||m_offs<0) m_offs=0;
152 int Available() const // bytes available
154 return m_avail;
158 int GetPtr(int offset, void **buf) const // returns bytes available in this block
160 offset += m_offs;
162 int x=0;
163 fqBuf *mq;
164 while ((mq=m_queue.Get(x)))
166 const int sz=mq->used;
167 if (offset < sz)
169 *buf = (char *)mq->data + offset;
170 return sz-offset;
172 x++;
173 offset -= sz;
175 *buf=NULL;
176 return 0;
179 int SetFromBuf(int offs, void *buf, int len) // returns length set
181 int pos=0;
182 while (len > 0)
184 void *p=NULL;
185 int l=GetPtr(offs+pos,&p);
186 if (!l || !p) break;
187 if (l > len) l=len;
188 memcpy(p,(char *)buf + pos,l);
189 pos += l;
190 len -= l;
192 return pos;
195 int GetToBuf(int offs, void *buf, int len) const
197 int pos=0;
198 while (len > 0)
200 void *p=NULL;
201 int l=GetPtr(offs+pos,&p);
202 if (!l || !p) break;
203 if (l > len) l=len;
204 memcpy((char *)buf + pos,p,l);
205 pos += l;
206 len -= l;
208 return pos;
211 private:
213 WDL_PtrList<fqBuf> m_queue, m_empties;
214 int m_offs;
215 int m_avail;
216 int m_bsize;
217 int m_maxemptieskeep;
218 } WDL_FIXALIGN;
221 #endif //_WDL_FASTQUEUE_H_