attributeHandler.hpp 11.7 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21 22 23 24
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

Sylvain Thery's avatar
Sylvain Thery committed
25 26 27 28
#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <vector>

Pierre Kraemer's avatar
Pierre Kraemer committed
29 30 31
namespace CGoGN
{

Pierre Kraemer's avatar
Pierre Kraemer committed
32 33
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline void AttributeHandler<T, ORBIT, MAP_IMPL>::registerInMap()
34
{
35
	boost::mutex::scoped_lock lockAH(m_map->attributeHandlersMutex);
36 37 38
	m_map->attributeHandlers.insert(std::pair<AttributeMultiVectorGen*, AttributeHandlerGen*>(m_attrib, this)) ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
39 40
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline void AttributeHandler<T, ORBIT, MAP_IMPL>::unregisterFromMap()
41 42
{
	typedef std::multimap<AttributeMultiVectorGen*, AttributeHandlerGen*>::iterator IT ;
43 44

	boost::mutex::scoped_lock lockAH(m_map->attributeHandlersMutex);
45 46 47 48 49 50 51 52 53 54 55 56 57 58
	std::pair<IT, IT> bounds = m_map->attributeHandlers.equal_range(m_attrib) ;
	for(IT i = bounds.first; i != bounds.second; ++i)
	{
		if((*i).second == this)
		{
			m_map->attributeHandlers.erase(i) ;
			return ;
		}
	}
	assert(false || !"Should not get here") ;
}

// =================================================================

Pierre Kraemer's avatar
Pierre Kraemer committed
59 60 61 62 63
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
AttributeHandler<T, ORBIT, MAP_IMPL>::AttributeHandler() :
	AttributeHandlerGen(false),
	m_map(NULL),
	m_attrib(NULL)
64
{}
Pierre Kraemer's avatar
Pierre Kraemer committed
65

Pierre Kraemer's avatar
Pierre Kraemer committed
66 67 68 69 70
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
AttributeHandler<T, ORBIT, MAP_IMPL>::AttributeHandler(MapCommon<MAP_IMPL>* m, AttributeMultiVector<T>* amv) :
	AttributeHandlerGen(false),
	m_map(m),
	m_attrib(amv)
71
{
72
	if(m != NULL && amv != NULL && amv->getIndex() != AttributeContainer::UNKNOWN)
73
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
74
		assert(ORBIT == amv->getOrbit() || !"AttributeHandler: orbit incompatibility") ;
75 76 77 78 79
		valid = true ;
		registerInMap() ;
	}
	else
		valid = false ;
80
}
81

Pierre Kraemer's avatar
Pierre Kraemer committed
82 83 84 85
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
AttributeHandler<T, ORBIT, MAP_IMPL>::AttributeHandler(const AttributeHandler<T, ORBIT, MAP_IMPL>& ta) :
	AttributeHandlerGen(ta.valid),
	m_map(ta.m_map),
86
	m_attrib(ta.m_attrib)
87
{
88 89
	if(valid)
		registerInMap() ;
90
}
Pierre Kraemer's avatar
Pierre Kraemer committed
91

Pierre Kraemer's avatar
Pierre Kraemer committed
92
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
untereiner's avatar
untereiner committed
93
template <unsigned int ORBIT2>
Pierre Kraemer's avatar
Pierre Kraemer committed
94 95 96 97
AttributeHandler<T, ORBIT, MAP_IMPL>::AttributeHandler(const AttributeHandler<T, ORBIT2, MAP_IMPL>& h) :
	AttributeHandlerGen(h.valid),
	m_map(h.m_map),
	m_attrib(h.m_attrib)
untereiner's avatar
untereiner committed
98 99 100 101 102 103 104 105 106 107
{
	if(m_attrib->getOrbit() == ORBIT2)
	{
		if(valid)
			registerInMap() ;
	}
	else
		valid = false;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
108 109
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline AttributeHandler<T, ORBIT, MAP_IMPL>& AttributeHandler<T, ORBIT, MAP_IMPL>::operator=(const AttributeHandler<T, ORBIT, MAP_IMPL>& ta)
Pierre Kraemer's avatar
Pierre Kraemer committed
110
{
111 112 113
	if(valid)
		unregisterFromMap() ;
	m_map = ta.m_map ;
Pierre Kraemer's avatar
Pierre Kraemer committed
114
	m_attrib = ta.m_attrib ;
115 116 117
	valid = ta.valid ;
	if(valid)
		registerInMap() ;
Pierre Kraemer's avatar
bla  
Pierre Kraemer committed
118
	return *this ;
Pierre Kraemer's avatar
Pierre Kraemer committed
119 120
}

Pierre Kraemer's avatar
Pierre Kraemer committed
121
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
untereiner's avatar
untereiner committed
122
template <unsigned int ORBIT2>
Pierre Kraemer's avatar
Pierre Kraemer committed
123
inline AttributeHandler<T, ORBIT, MAP_IMPL>& AttributeHandler<T, ORBIT, MAP_IMPL>::operator=(const AttributeHandler<T, ORBIT2, MAP_IMPL>& ta)
untereiner's avatar
untereiner committed
124 125 126 127 128 129 130 131 132 133 134
{
	if(valid)
		unregisterFromMap() ;
	m_map = ta.map() ;
	m_attrib = ta.getDataVector() ;
	valid = ta.isValid() ;
	if(valid)
		registerInMap() ;
	return *this ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
135 136
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
AttributeHandler<T, ORBIT, MAP_IMPL>::~AttributeHandler()
137
{
138 139
	if(valid)
		unregisterFromMap() ;
140
}
Pierre Kraemer's avatar
Pierre Kraemer committed
141

Pierre Kraemer's avatar
Pierre Kraemer committed
142 143
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline AttributeMultiVector<T>* AttributeHandler<T, ORBIT, MAP_IMPL>::getDataVector() const
Pierre Kraemer's avatar
Pierre Kraemer committed
144 145 146 147
{
	return m_attrib ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
148 149
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline AttributeMultiVectorGen* AttributeHandler<T, ORBIT, MAP_IMPL>::getDataVectorGen() const
150 151 152 153
{
	return m_attrib ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
154 155
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline int AttributeHandler<T, ORBIT, MAP_IMPL>::getSizeOfType() const
156 157 158 159
{
	return sizeof(T) ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
160 161
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::getOrbit() const
Pierre Kraemer's avatar
Pierre Kraemer committed
162
{
163
	return ORBIT ;
164 165
}

Pierre Kraemer's avatar
Pierre Kraemer committed
166 167
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::getIndex() const
168 169
{
	return m_attrib->getIndex() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
170 171
}

Pierre Kraemer's avatar
Pierre Kraemer committed
172 173
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline const std::string& AttributeHandler<T, ORBIT, MAP_IMPL>::name() const
Pierre Kraemer's avatar
Pierre Kraemer committed
174
{
175
	return m_attrib->getName() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
176 177
}

Pierre Kraemer's avatar
Pierre Kraemer committed
178 179
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline const std::string& AttributeHandler<T, ORBIT, MAP_IMPL>::typeName() const
180 181 182
{
	return m_attrib->getTypeName();
}
183

184

Pierre Kraemer's avatar
Pierre Kraemer committed
185 186
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::nbElements() const
187
{
Pierre Kraemer's avatar
Pierre Kraemer committed
188
	return m_map->template getAttributeContainer<ORBIT>().size() ;
189 190
}

Pierre Kraemer's avatar
Pierre Kraemer committed
191
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
Pierre Kraemer's avatar
Pierre Kraemer committed
192
inline T& AttributeHandler<T, ORBIT, MAP_IMPL>::operator[](Cell<ORBIT> c)
Pierre Kraemer's avatar
Pierre Kraemer committed
193
{
194
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
195
	unsigned int a = m_map->getEmbedding(c) ;
196

Sylvain Thery's avatar
Sylvain Thery committed
197
	if (a == EMBNULL)
Pierre Kraemer's avatar
Pierre Kraemer committed
198
		a = m_map->template setOrbitEmbeddingOnNewCell(c) ;
199

200
	return m_attrib->operator[](a) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
201 202
}

Pierre Kraemer's avatar
Pierre Kraemer committed
203
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
Pierre Kraemer's avatar
Pierre Kraemer committed
204
inline const T& AttributeHandler<T, ORBIT, MAP_IMPL>::operator[](Cell<ORBIT> c) const
Pierre Kraemer's avatar
Pierre Kraemer committed
205
{
206
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
207
	unsigned int a = m_map->getEmbedding(c) ;
208
	return m_attrib->operator[](a) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
209 210
}

Pierre Kraemer's avatar
Pierre Kraemer committed
211 212
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline T& AttributeHandler<T, ORBIT, MAP_IMPL>::operator[](unsigned int a)
Pierre Kraemer's avatar
Pierre Kraemer committed
213
{
214
	assert(valid || !"Invalid AttributeHandler") ;
215
	return m_attrib->operator[](a) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
216 217
}

Pierre Kraemer's avatar
Pierre Kraemer committed
218 219
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline const T& AttributeHandler<T, ORBIT, MAP_IMPL>::operator[](unsigned int a) const
Pierre Kraemer's avatar
Pierre Kraemer committed
220
{
221
	assert(valid || !"Invalid AttributeHandler") ;
222
	return m_attrib->operator[](a) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
223 224
}

Pierre Kraemer's avatar
Pierre Kraemer committed
225 226
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::insert(const T& elt)
Pierre Kraemer's avatar
Pierre Kraemer committed
227
{
228
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
229
	unsigned int idx = m_map->template getAttributeContainer<ORBIT>().insertLine() ;
230 231
	m_attrib->operator[](idx) = elt ;
	return idx ;
Pierre Kraemer's avatar
Pierre Kraemer committed
232 233
}

Pierre Kraemer's avatar
Pierre Kraemer committed
234 235
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::newElt()
Pierre Kraemer's avatar
Pierre Kraemer committed
236
{
237
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
238
	unsigned int idx = m_map->template getAttributeContainer<ORBIT>().insertLine() ;
239
	return idx ;
Pierre Kraemer's avatar
Pierre Kraemer committed
240 241
}

Pierre Kraemer's avatar
Pierre Kraemer committed
242 243
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline void AttributeHandler<T, ORBIT, MAP_IMPL>::setAllValues(const T& v)
244 245 246 247 248
{
	for(unsigned int i = begin(); i != end(); next(i))
		m_attrib->operator[](i) = v ;
}

Pierre Kraemer's avatar
Pierre Kraemer committed
249 250
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::begin() const
Pierre Kraemer's avatar
Pierre Kraemer committed
251
{
252
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
253
	return m_map->template getAttributeContainer<ORBIT>().begin() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
254 255
}

Pierre Kraemer's avatar
Pierre Kraemer committed
256 257
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline unsigned int AttributeHandler<T, ORBIT, MAP_IMPL>::end() const
Pierre Kraemer's avatar
Pierre Kraemer committed
258
{
259
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
260
	return m_map->template getAttributeContainer<ORBIT>().end() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
261 262
}

Pierre Kraemer's avatar
Pierre Kraemer committed
263 264
template <typename T, unsigned int ORBIT, typename MAP_IMPL>
inline void AttributeHandler<T, ORBIT, MAP_IMPL>::next(unsigned int& iter) const
Pierre Kraemer's avatar
Pierre Kraemer committed
265
{
266
	assert(valid || !"Invalid AttributeHandler") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
267
	m_map->template getAttributeContainer<ORBIT>().next(iter) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
268 269
}

Sylvain Thery's avatar
Sylvain Thery committed
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

namespace Parallel
{

template <typename FUNC>
class ThreadFunctionAttrib
{
protected:
	std::vector<unsigned int>& m_ids;
	boost::barrier& m_sync1;
	boost::barrier& m_sync2;
	bool& m_finished;
	unsigned int m_id;
	FUNC m_lambda;
public:
	ThreadFunctionAttrib(FUNC func, std::vector<unsigned int>& vid, boost::barrier& s1, boost::barrier& s2, bool& finished, unsigned int id):
		m_ids(vid), m_sync1(s1), m_sync2(s2), m_finished(finished), m_id(id), m_lambda(func)
	{
	}

	ThreadFunctionAttrib(const ThreadFunctionAttrib& tf):
		m_ids(tf.m_ids), m_sync1(tf.m_sync1), m_sync2(tf.m_sync2), m_finished(tf.m_finished), m_id(tf.m_id), m_lambda(tf.m_lambda){}

	void operator()()
	{
		while (!m_finished)
		{
			for (std::vector<unsigned int>::const_iterator it = m_ids.begin(); it != m_ids.end(); ++it)
				m_lambda(*it,m_id);
			m_sync1.wait();
			m_sync2.wait();
		}
	}
};



template <typename ATTR, typename FUNC>
Sylvain Thery's avatar
Sylvain Thery committed
308
void foreach_attribute(ATTR& attribute, FUNC func, unsigned int nbthread)
Sylvain Thery's avatar
Sylvain Thery committed
309
{
Sylvain Thery's avatar
Sylvain Thery committed
310 311
	// thread 0 is for attribute traversal
	unsigned int nbth = nbthread -1;
Sylvain Thery's avatar
Sylvain Thery committed
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380

	std::vector< unsigned int >* vd = new std::vector< unsigned int >[nbth];
	for (unsigned int i = 0; i < nbth; ++i)
		vd[i].reserve(SIZE_BUFFER_THREAD);

	unsigned int nb = 0;
	unsigned int attIdx = attribute.begin();
	while ((attIdx != attribute.end()) && (nb < nbth*SIZE_BUFFER_THREAD) )
	{
		vd[nb%nbth].push_back(attIdx);
		nb++;
		attribute.next(attIdx);
	}
	boost::barrier sync1(nbth+1);
	boost::barrier sync2(nbth+1);
	bool finished=false;


	boost::thread** threads = new boost::thread*[nbth];
	ThreadFunctionAttrib<FUNC>** tfs = new ThreadFunctionAttrib<FUNC>*[nbth];

	for (unsigned int i = 0; i < nbth; ++i)
	{
		tfs[i] = new ThreadFunctionAttrib<FUNC>(func, vd[i], sync1,sync2,finished,1+i);
		threads[i] = new boost::thread( boost::ref( *(tfs[i]) ) );
	}

	// and continue to traverse the map
	std::vector< unsigned int >* tempo = new std::vector< unsigned int >[nbth];
	for (unsigned int i = 0; i < nbth; ++i)
		tempo[i].reserve(SIZE_BUFFER_THREAD);

	while (attIdx != attribute.end())
	{
		for (unsigned int i = 0; i < nbth; ++i)
			tempo[i].clear();
		unsigned int nb = 0;

		while ((attIdx != attribute.end()) && (nb < nbth*SIZE_BUFFER_THREAD) )
		{
			tempo[nb%nbth].push_back(attIdx);
			nb++;
			attribute.next(attIdx);
		}
		sync1.wait();// wait for all thread to finish its vector
		for (unsigned int i = 0; i < nbth; ++i)
			vd[i].swap(tempo[i]);
		sync2.wait();// everybody refilled then go
	}

	sync1.wait();// wait for all thread to finish its vector
	finished = true;// say finsih to everyone
	sync2.wait(); // just wait for last barrier wait !

	//wait for all theads to be finished
	for (unsigned int i = 0; i < nbth; ++i)
	{
		threads[i]->join();
		delete threads[i];
		delete tfs[i];
	}
	delete[] tfs;
	delete[] threads;
	delete[] vd;
	delete[] tempo;
}

}

Pierre Kraemer's avatar
Pierre Kraemer committed
381
} //namespace CGoGN