attributeHandler.hpp 11.4 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() :
61
	AttributeHandlerOrbit<ORB>(false),
Pierre Kraemer's avatar
Pierre Kraemer committed
62 63
	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) :
68
	AttributeHandlerOrbit<ORB>(false),
Pierre Kraemer's avatar
Pierre Kraemer committed
69 70
	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
		this->valid = true ;
76 77 78
		registerInMap() ;
	}
	else
79
		this->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) :
84
	AttributeHandlerOrbit<ORB>(ta.valid),
Pierre Kraemer's avatar
Pierre Kraemer committed
85
	m_map(ta.m_map),
86
	m_attrib(ta.m_attrib)
87
{
88
	if(this->valid)
89
		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) :
95
	AttributeHandlerOrbit<ORB>(h.valid),
Pierre Kraemer's avatar
Pierre Kraemer committed
96 97
	m_map(h.m_map),
	m_attrib(h.m_attrib)
untereiner's avatar
untereiner committed
98 99 100
{
	if(m_attrib->getOrbit() == ORBIT2)
	{
101
		if(this->valid)
untereiner's avatar
untereiner committed
102 103 104
			registerInMap() ;
	}
	else
105
		this->valid = false;
untereiner's avatar
untereiner committed
106 107
}

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
	if(this->valid)
112 113
		unregisterFromMap() ;
	m_map = ta.m_map ;
Pierre Kraemer's avatar
Pierre Kraemer committed
114
	m_attrib = ta.m_attrib ;
115 116
	this->valid = ta.valid ;
	if(this->valid)
117
		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
	if(this->valid)
untereiner's avatar
untereiner committed
126 127 128
		unregisterFromMap() ;
	m_map = ta.map() ;
	m_attrib = ta.getDataVector() ;
129 130
	this->valid = ta.isValid() ;
	if(this->valid)
untereiner's avatar
untereiner committed
131 132 133 134
		registerInMap() ;
	return *this ;
}

135 136
template <typename T, unsigned int ORB, typename MAP>
AttributeHandler<T, ORB, MAP>::~AttributeHandler()
137
{
138
	if(this->valid)
139
		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(this->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(this->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(this->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(this->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(this->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(this->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(this->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(this->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(this->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