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