1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 /******************************************************************************
19 * $Id: datalistimpl.h 9655 2013-06-25 23:08:13Z xlou $
20 *
21 *****************************************************************************/
22
23 /** @file
24 * class XXX interface
25 */
26
27 #include <vector>
28 #include <set>
29 #include <typeinfo>
30 #include <stdexcept>
31 #include <cassert>
32 #include <sstream>
33
34 #include "datalist.h"
35
36 #ifndef _DATALISTIMPL_HPP_
37 #define _DATALISTIMPL_HPP_
38
39 namespace joblist
40 {
41
42 /** @brief class DataListImpl
43 *
44 */
45 template<typename container_t, typename element_t>
46 class DataListImpl : public DataList<element_t>
47 {
48
49 public:
50 DataListImpl(uint32_t numConsumers);
51 DataListImpl(const DataListImpl& dl);
52 virtual ~DataListImpl();
53
54 DataListImpl& operator=(const DataListImpl& dl);
55
56 // derived classes need to lock around these fcns
57 virtual void insert(const element_t& e);
58 virtual void insert(const std::vector<element_t>& v);
59 virtual uint64_t getIterator();
60 virtual bool next(uint64_t it, element_t* e);
61
62 virtual void setNumConsumers(uint32_t);
63 virtual uint32_t getNumConsumers() const;
64 void resetNumConsumers(uint32_t numConsumers);
65
66 protected:
67 bool endOfData(uint64_t id) const;
68 void eraseUpTo(uint64_t id);
69 void reset();
70 virtual void shrink();
71 typename container_t::iterator iInsert(const element_t& e);
72
73 container_t* c;
74 typename container_t::iterator* cIterators;
75 uint64_t numConsumers;
76 uint64_t itIndex;
77
78 private:
79 explicit DataListImpl();
80 };
81
82 template<typename container_t, typename element_t>
DataListImpl()83 DataListImpl<container_t, element_t>::DataListImpl() : DataList<element_t>(), c(0), cIterators(0), numConsumers(0),
84 itIndex(0)
85 { }
86
87 template<typename container_t, typename element_t>
setNumConsumers(uint32_t nc)88 void DataListImpl<container_t, element_t>::setNumConsumers(uint32_t nc)
89 {
90 resetNumConsumers(nc);
91 }
92
93 template<typename container_t, typename element_t>
getNumConsumers()94 uint32_t DataListImpl<container_t, element_t>::getNumConsumers() const
95 {
96 return numConsumers;
97 }
98
99 template<typename container_t, typename element_t>
resetNumConsumers(uint32_t nc)100 void DataListImpl<container_t, element_t>::resetNumConsumers(uint32_t nc)
101 {
102 if (itIndex != 0)
103 throw std::logic_error("DataListImpl::resetNumConsumers(): attempt to change numConsumers "
104 "after iterators have been issued");
105
106 uint32_t i;
107
108 numConsumers = nc;
109 delete [] cIterators;
110 cIterators = new typename container_t::iterator[numConsumers];
111
112 for (i = 0; i < numConsumers; i++)
113 cIterators[i] = c->end();
114 }
115
116 template<typename container_t, typename element_t>
DataListImpl(uint32_t nc)117 DataListImpl<container_t, element_t>::DataListImpl(uint32_t nc) : DataList<element_t>()
118 {
119 uint32_t i;
120
121 numConsumers = nc;
122 itIndex = 0;
123 c = new container_t();
124 cIterators = new typename container_t::iterator[numConsumers];
125
126 for (i = 0; i < numConsumers; i++)
127 cIterators[i] = c->end();
128 }
129
130 template<typename container_t, typename element_t>
DataListImpl(const DataListImpl<container_t,element_t> & dl)131 DataListImpl<container_t, element_t>::DataListImpl
132 (const DataListImpl<container_t, element_t>& dl)
133 : DataList<element_t>(dl)
134 {
135 int i;
136
137 c = dl.c;
138 numConsumers = dl.numConsumers;
139 itIndex = dl.itIndex;
140
141 //delete [] cIterators;
142 cIterators = new typename container_t::iterator[numConsumers];
143
144 for (i = 0; i < numConsumers; i++)
145 cIterators[i] = dl.cIterators[i];
146 };
147
148 template<typename container_t, typename element_t>
~DataListImpl()149 DataListImpl<container_t, element_t>::~DataListImpl()
150 {
151 delete c;
152 delete [] cIterators;
153 };
154
155 // lock at a higher level
156 template<typename container_t, typename element_t>
157 DataListImpl<container_t, element_t>& DataListImpl<container_t, element_t>::operator=
158 (const DataListImpl<container_t, element_t>& dl)
159 {
160 uint64_t i;
161
162 static_cast<DataList<element_t> >(*this) =
163 static_cast<DataList<element_t> >(dl);
164 delete c;
165 c = dl.c;
166 numConsumers = dl.numConsumers;
167 itIndex = dl.itIndex;
168
169 delete [] cIterators;
170 cIterators = new typename container_t::iterator[numConsumers];
171
172 for (i = 0; i < numConsumers; i++)
173 cIterators[i] = dl.cIterators[i];
174
175 return *this;
176 };
177
178 template<typename container_t, typename element_t>
getIterator()179 uint64_t DataListImpl<container_t, element_t>::getIterator()
180 {
181 if (itIndex >= numConsumers)
182 {
183 std::ostringstream oss;
184 oss << "DataListImpl::getIterator(): caller attempted to grab too many iterators: " <<
185 "have " << numConsumers << " asked for " << (itIndex + 1);
186 throw std::logic_error(oss.str().c_str());
187 }
188
189 cIterators[itIndex] = c->begin();
190 return itIndex++;
191 }
192
193 template<typename container_t, typename element_t>
insert(const element_t & e)194 inline void DataListImpl<container_t, element_t>::insert(const element_t& e)
195 {
196 c->insert(c->end(), e);
197 }
198
199 template<typename container_t, typename element_t>
insert(const std::vector<element_t> & v)200 inline void DataListImpl<container_t, element_t>::insert(const std::vector<element_t>& v)
201 {
202 if (typeid(container_t) == typeid(std::vector<element_t>))
203 {
204 std::vector<element_t>* vc = (std::vector<element_t>*) c;
205 vc->insert(vc->end(), v.begin(), v.end());
206 }
207 else
208 throw std::logic_error("insert(vector) isn't supported for non-vector-based DLs yet");
209 }
210
211 template<typename container_t, typename element_t>
iInsert(const element_t & e)212 inline typename container_t::iterator DataListImpl<container_t, element_t>::iInsert(const element_t& e)
213 {
214 return c->insert(c->end(), e);
215 }
216
217 template<typename container_t, typename element_t>
next(uint64_t id,element_t * e)218 inline bool DataListImpl<container_t, element_t>::next(uint64_t id, element_t* e)
219 {
220
221 // idbassert(id < numConsumers);
222 if (c == 0 || cIterators[id] == c->end())
223 return false;
224
225 *e = *(cIterators[id]);
226 cIterators[id]++;
227 return true;
228 }
229
230 template<typename container_t, typename element_t>
endOfData(uint64_t id)231 bool DataListImpl<container_t, element_t>::endOfData(uint64_t id) const
232 {
233 idbassert(id < numConsumers);
234 return (cIterators[id] == c->end());
235 }
236
237 template<typename container_t, typename element_t>
eraseUpTo(uint64_t id)238 void DataListImpl<container_t, element_t>::eraseUpTo(uint64_t id)
239 {
240 idbassert(id < numConsumers);
241 #ifdef DEBUG
242 uint64_t i;
243 typename container_t::iterator it;
244
245 for (it = c->begin(), i = 0; it != cIterators[id]; it++, i++) ;
246
247 std::cout << "DLI: erasing " << i << " elements" << std::endl;
248 #endif
249
250 c->erase(c->begin(), cIterators[id]);
251 };
252
253 template<typename container_t, typename element_t>
reset()254 void DataListImpl<container_t, element_t>::reset()
255 {
256 uint64_t i;
257
258 delete c;
259 c = new container_t();
260
261 for (i = 0; i < numConsumers; i++)
262 cIterators[i] = c->begin();
263 }
264
265 template<typename container_t, typename element_t>
shrink()266 void DataListImpl<container_t, element_t>::shrink()
267 {
268
269 delete c;
270 c = 0;
271 }
272
273 } //namespace
274
275 #endif
276