attributeHandler.hpp 11.3 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
#include "Utils/threadbarrier.h"

Sylvain Thery's avatar
Sylvain Thery committed
27 28
#include <vector>

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

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

39 40
template <typename T, unsigned int ORB, typename MAP>
inline void AttributeHandler<T, ORB, MAP>::unregisterFromMap()
41 42
{
	typedef std::multimap<AttributeMultiVectorGen*, AttributeHandlerGen*>::iterator IT ;
43

Sylvain Thery's avatar
Sylvain Thery committed
44
	std::lock_guard<std::mutex> 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") ;
}

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

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

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

82 83
template <typename T, unsigned int ORB, typename MAP>
AttributeHandler<T, ORB, MAP>::AttributeHandler(const AttributeHandler<T, ORB, MAP>& ta) :
Pierre Kraemer's avatar
Pierre Kraemer committed
84 85
	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

92
template <typename T, unsigned int ORB, typename MAP>
untereiner's avatar
untereiner committed
93
template <unsigned int ORBIT2>
94
AttributeHandler<T, ORB, MAP>::AttributeHandler(const AttributeHandler<T, ORBIT2, MAP>& h) :
Pierre Kraemer's avatar
Pierre Kraemer committed
95 96 97
	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;
}

108 109
template <typename T, unsigned int ORB, typename MAP>
inline AttributeHandler<T, ORB, MAP>& AttributeHandler<T, ORB, MAP>::operator=(const AttributeHandler<T, ORB, MAP>& 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
}

121
template <typename T, unsigned int ORB, typename MAP>
untereiner's avatar
untereiner committed
122
template <unsigned int ORBIT2>
123
inline AttributeHandler<T, ORB, MAP>& AttributeHandler<T, ORB, MAP>::operator=(const AttributeHandler<T, ORBIT2, MAP>& 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 ;
}

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

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

148 149
template <typename T, unsigned int ORB, typename MAP>
inline AttributeMultiVectorGen* AttributeHandler<T, ORB, MAP>::getDataVectorGen() const
150 151 152 153
{
	return m_attrib ;
}

154 155
template <typename T, unsigned int ORB, typename MAP>
inline int AttributeHandler<T, ORB, MAP>::getSizeOfType() const
156 157 158 159
{
	return sizeof(T) ;
}

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

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

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

178 179
template <typename T, unsigned int ORB, typename MAP>
inline const std::string& AttributeHandler<T, ORB, MAP>::typeName() const
180 181 182
{
	return m_attrib->getTypeName();
}
183

184

185 186
template <typename T, unsigned int ORB, typename MAP>
inline unsigned int AttributeHandler<T, ORB, MAP>::nbElements() const
187
{
188
	return m_map->template getAttributeContainer<ORB>().size() ;
189 190
}

191 192
template <typename T, unsigned int ORB, typename MAP>
inline T& AttributeHandler<T, ORB, MAP>::operator[](Cell<ORB> 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)
198
		a = Algo::Topo::setOrbitEmbeddingOnNewCell(*m_map, c) ;
199

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

203 204
template <typename T, unsigned int ORB, typename MAP>
inline const T& AttributeHandler<T, ORB, MAP>::operator[](Cell<ORB> 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
}

211 212
template <typename T, unsigned int ORB, typename MAP>
inline T& AttributeHandler<T, ORB, MAP>::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
}

218 219
template <typename T, unsigned int ORB, typename MAP>
inline const T& AttributeHandler<T, ORB, MAP>::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
}

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

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

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

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

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

263 264
template <typename T, unsigned int ORB, typename MAP>
inline void AttributeHandler<T, ORB, MAP>::next(unsigned int& iter) const
Pierre Kraemer's avatar
Pierre Kraemer committed
265
{
266
	assert(valid || !"Invalid AttributeHandler") ;
267
	m_map->template getAttributeContainer<ORB>().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

namespace Parallel
{

template <typename FUNC>
class ThreadFunctionAttrib
{
protected:
	std::vector<unsigned int>& m_ids;
Sylvain Thery's avatar
Sylvain Thery committed
279 280
	Utils::Barrier& m_sync1;
	Utils::Barrier& m_sync2;
Sylvain Thery's avatar
Sylvain Thery committed
281 282 283 284
	bool& m_finished;
	unsigned int m_id;
	FUNC m_lambda;
public:
Sylvain Thery's avatar
Sylvain Thery committed
285
	ThreadFunctionAttrib(FUNC func, std::vector<unsigned int>& vid, Utils::Barrier& s1, Utils::Barrier& s2, bool& finished, unsigned int id):
Sylvain Thery's avatar
Sylvain Thery committed
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
		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

	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);
	}
Sylvain Thery's avatar
Sylvain Thery committed
325 326
	Utils::Barrier sync1(nbth+1);
	Utils::Barrier sync2(nbth+1);
Sylvain Thery's avatar
Sylvain Thery committed
327 328 329
	bool finished=false;


Sylvain Thery's avatar
Sylvain Thery committed
330
	std::thread** threads = new std::thread*[nbth];
Sylvain Thery's avatar
Sylvain Thery committed
331 332 333 334
	ThreadFunctionAttrib<FUNC>** tfs = new ThreadFunctionAttrib<FUNC>*[nbth];

	for (unsigned int i = 0; i < nbth; ++i)
	{
Sylvain Thery's avatar
Sylvain Thery committed
335
		tfs[i] = new ThreadFunctionAttrib<FUNC>(func, vd[i], sync1,sync2,finished,i);
Sylvain Thery's avatar
Sylvain Thery committed
336
		threads[i] = new std::thread( std::ref( *(tfs[i]) ) );
Sylvain Thery's avatar
Sylvain Thery committed
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
	}

	// 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