9 #include <argos3/core/simulator/simulator.h>
10 #include <argos3/core/utility/profiler/profiler.h>
26 static void CleanupUpdateThread(
void* p_data) {
31 SCleanupUpdateThreadData& sData =
32 *
reinterpret_cast<SCleanupUpdateThreadData*
>(p_data);
33 pthread_mutex_unlock(sData.SenseControlStepConditionalMutex);
34 pthread_mutex_unlock(sData.ActConditionalMutex);
35 pthread_mutex_unlock(sData.PhysicsConditionalMutex);
36 pthread_mutex_unlock(sData.MediaConditionalMutex);
37 pthread_mutex_unlock(sData.EntityIterConditionalMutex);
41 LOG.AddThreadSafeBuffer();
42 LOGERR.AddThreadSafeBuffer();
43 auto* psData =
reinterpret_cast<CSpaceMultiThreadBalanceQuantity::SUpdateThreadData*
>(p_data);
44 psData->Space->UpdateThread(psData->ThreadId);
52 m_psUpdateThreadData(nullptr),
53 m_ptUpdateThreads(nullptr),
54 m_bIsControllableEntityAssignmentRecalculationNeeded(true) {}
72 if((nErrors = pthread_mutex_init(&m_tSenseControlStepConditionalMutex,
nullptr)) ||
73 (nErrors = pthread_mutex_init(&m_tActConditionalMutex,
nullptr)) ||
74 (nErrors = pthread_mutex_init(&m_tPhysicsConditionalMutex,
nullptr)) ||
75 (nErrors = pthread_mutex_init(&m_tMediaConditionalMutex,
nullptr)) ||
76 (nErrors = pthread_mutex_init(&m_tEntityIterConditionalMutex,
nullptr))) {
80 if((nErrors = pthread_cond_init(&m_tSenseControlStepConditional,
nullptr)) ||
81 (nErrors = pthread_cond_init(&m_tActConditional,
nullptr)) ||
82 (nErrors = pthread_cond_init(&m_tPhysicsConditional,
nullptr)) ||
83 (nErrors = pthread_cond_init(&m_tMediaConditional,
nullptr)) ||
84 (nErrors = pthread_cond_init(&m_tEntityIterConditional,
nullptr))) {
94 void CSpaceMultiThreadBalanceQuantity::StartThreads() {
101 m_psUpdateThreadData[i] =
new SUpdateThreadData(i,
this);
103 if((nErrors = pthread_create(m_ptUpdateThreads + i,
106 reinterpret_cast<void*
>(m_psUpdateThreadData[i])))) {
118 if(m_ptUpdateThreads !=
nullptr) {
120 if((nErrors = pthread_cancel(m_ptUpdateThreads[i]))) {
121 THROW_ARGOSEXCEPTION(
"Error canceling controllable entities update threads " << ::strerror(nErrors));
126 if((nErrors = pthread_join(m_ptUpdateThreads[i], ppJoinResult + i))) {
127 THROW_ARGOSEXCEPTION(
"Error joining controllable entities update threads " << ::strerror(nErrors));
129 if(ppJoinResult[i] != PTHREAD_CANCELED) {
130 LOGERR <<
"[WARNING] Controllable entities update thread #" << i<<
" not canceled" << std::endl;
133 delete[] ppJoinResult;
135 delete[] m_ptUpdateThreads;
137 if(m_psUpdateThreadData !=
nullptr) {
139 delete m_psUpdateThreadData[i];
142 delete[] m_psUpdateThreadData;
143 pthread_mutex_destroy(&m_tSenseControlStepConditionalMutex);
144 pthread_mutex_destroy(&m_tActConditionalMutex);
145 pthread_mutex_destroy(&m_tPhysicsConditionalMutex);
146 pthread_mutex_destroy(&m_tMediaConditionalMutex);
147 pthread_mutex_destroy(&m_tEntityIterConditionalMutex);
149 pthread_cond_destroy(&m_tSenseControlStepConditional);
150 pthread_cond_destroy(&m_tActConditional);
151 pthread_cond_destroy(&m_tPhysicsConditional);
152 pthread_cond_destroy(&m_tMediaConditional);
153 pthread_cond_destroy(&m_tEntityIterConditional);
163 m_bIsControllableEntityAssignmentRecalculationNeeded =
true;
171 m_bIsControllableEntityAssignmentRecalculationNeeded =
true;
178 #define MAIN_SEND_GO_FOR_PHASE(PHASE) \
181 pthread_mutex_lock(&m_t ## PHASE ## ConditionalMutex); \
182 m_un ## PHASE ## PhaseDoneCounter = 0; \
183 pthread_cond_broadcast(&m_t ## PHASE ## Conditional); \
184 pthread_mutex_unlock(&m_t ## PHASE ## ConditionalMutex);
186 #define MAIN_WAIT_FOR_PHASE_END(PHASE) \
187 pthread_mutex_lock(&m_t ## PHASE ## ConditionalMutex); \
188 while(m_un ## PHASE ## PhaseDoneCounter < CSimulator::GetInstance().GetNumThreads()) { \
189 pthread_cond_wait(&m_t ## PHASE ## Conditional, &m_t ## PHASE ## ConditionalMutex); \
191 pthread_mutex_unlock(&m_t ## PHASE ## ConditionalMutex);
197 m_bIsControllableEntityAssignmentRecalculationNeeded =
false;
210 (*m_ptPhysicsEngines)[i]->TransferEntities();
239 void CSpaceMultiThreadBalanceQuantity::ControllableEntityIterationWaitAbort(
void) {
251 m_bIsControllableEntityAssignmentRecalculationNeeded =
false;
257 #define THREAD_WAIT_FOR_GO_SIGNAL(PHASE) \
258 pthread_mutex_lock(&m_t ## PHASE ## ConditionalMutex); \
259 while(m_un ## PHASE ## PhaseDoneCounter == CSimulator::GetInstance().GetNumThreads()) { \
260 pthread_cond_wait(&m_t ## PHASE ## Conditional, &m_t ## PHASE ## ConditionalMutex); \
262 pthread_mutex_unlock(&m_t ## PHASE ## ConditionalMutex); \
263 pthread_testcancel();
265 #define THREAD_SIGNAL_PHASE_DONE(PHASE) \
266 pthread_mutex_lock(&m_t ## PHASE ## ConditionalMutex); \
267 ++m_un ## PHASE ## PhaseDoneCounter; \
268 pthread_cond_broadcast(&m_t ## PHASE ## Conditional); \
269 pthread_mutex_unlock(&m_t ## PHASE ## ConditionalMutex); \
270 pthread_testcancel();
273 size_t un_tot_plugins) {
279 if(unMinPortion == 0) {
281 if(un_id < unExtraPortion) {
292 if(un_id < unExtraPortion) {
295 (un_id+1) * (unMinPortion+1));
299 return CRange<size_t>(unExtraPortion * (unMinPortion+1) + (un_id-unExtraPortion) * unMinPortion,
300 unExtraPortion * (unMinPortion+1) + (un_id-unExtraPortion+1) * unMinPortion);
305 void CSpaceMultiThreadBalanceQuantity::UpdateThread(
UInt32 un_id) {
309 SCleanupUpdateThreadData sCancelData;
310 sCancelData.SenseControlStepConditionalMutex = &m_tSenseControlStepConditionalMutex;
311 sCancelData.ActConditionalMutex = &m_tActConditionalMutex;
312 sCancelData.PhysicsConditionalMutex = &m_tPhysicsConditionalMutex;
313 sCancelData.MediaConditionalMutex = &m_tMediaConditionalMutex;
314 sCancelData.EntityIterConditionalMutex = &m_tEntityIterConditionalMutex;
316 pthread_cleanup_push(CleanupUpdateThread, &sCancelData);
332 CRange<size_t> cEntityRange;
335 UpdateThreadEntityAct(un_id, cEntityRange);
338 UpdateThreadPhysics(cPhysicsRange);
341 UpdateThreadMedia(cMediaRange);
344 UpdateThreadIterateOverEntities(un_id, cEntityRange);
347 UpdateThreadEntitySenseControl(un_id, cEntityRange);
350 UpdateThreadIterateOverEntities(un_id, cEntityRange);
353 pthread_cleanup_pop(1);
359 void CSpaceMultiThreadBalanceQuantity::UpdateThreadEntityAct(
UInt32 un_id,
360 CRange<size_t>& c_range) {
363 if (m_bIsControllableEntityAssignmentRecalculationNeeded) {
368 if (c_range.GetSpan() > 0) {
371 for(
size_t i = c_range.GetMin(); i < c_range.GetMax(); ++i) {
375 pthread_testcancel();
387 void CSpaceMultiThreadBalanceQuantity::UpdateThreadPhysics(
388 const CRange<size_t>& c_range) {
391 if (c_range.GetSpan() > 0) {
393 for (
size_t i = c_range.GetMin(); i < c_range.GetMax(); ++i) {
394 (*m_ptPhysicsEngines)[i]->Update();
396 pthread_testcancel();
408 void CSpaceMultiThreadBalanceQuantity::UpdateThreadMedia(
409 const CRange<size_t>& c_range) {
412 if(c_range.GetSpan() > 0) {
414 for(
size_t i = c_range.GetMin(); i < c_range.GetMax(); ++i) {
415 (*m_ptMedia)[i]->Update();
417 pthread_testcancel();
429 void CSpaceMultiThreadBalanceQuantity::UpdateThreadIterateOverEntities(
UInt32 un_id,
430 CRange<size_t>& c_range) {
433 if (m_bIsControllableEntityAssignmentRecalculationNeeded) {
440 for (
size_t i = c_range.GetMin(); i < c_range.GetMax(); ++i) {
443 pthread_testcancel();
454 void CSpaceMultiThreadBalanceQuantity::UpdateThreadEntitySenseControl(
UInt32 un_id,
455 CRange<size_t>& c_range) {
460 if (m_bIsControllableEntityAssignmentRecalculationNeeded) {
465 if (c_range.GetSpan() > 0) {
467 for (
size_t i = c_range.GetMin(); i < c_range.GetMax(); ++i) {
473 pthread_testcancel();
#define THREAD_WAIT_FOR_GO_SIGNAL(PHASE)
#define MAIN_SEND_GO_FOR_PHASE(PHASE)
#define MAIN_WAIT_FOR_PHASE_END(PHASE)
#define THREAD_SIGNAL_PHASE_DONE(PHASE)
#define THROW_ARGOSEXCEPTION(message)
This macro throws an ARGoS exception with the passed message.
unsigned int UInt32
32-bit unsigned integer.
The namespace containing all the ARGoS related code.
CRange< size_t > CalculatePluginRangeForThread(size_t un_id, size_t un_tot_plugins)
CARGoSLog LOGERR(std::cerr, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_RED))
ticpp::Element TConfigurationNode
The ARGoS configuration XML node.
CARGoSLog LOG(std::cout, SLogColor(ARGOS_LOG_ATTRIBUTE_BRIGHT, ARGOS_LOG_COLOR_GREEN))
void * LaunchUpdateThreadBalanceQuantity(void *p_data)
An entity that contains a pointer to the user-defined controller.
CProfiler & GetProfiler()
Returns a reference to the profiler.
static CSimulator & GetInstance()
Returns the instance to the CSimulator class.
UInt32 GetNumThreads() const
Returns the number of threads used during the experiment.
bool IsProfiling() const
Returns true if ARGoS is being profiled.
CControllableEntity::TVector m_vecControllableEntities
A vector of controllable entities.
virtual void Init(TConfigurationNode &t_tree)
Initializes the space using the <arena> section of the XML configuration file.
virtual void Destroy()
Destroys the space and all its entities.
bool ControllableEntityIterationEnabled() const
CPhysicsEngine::TVector * m_ptPhysicsEngines
A pointer to the list of physics engines.
TControllableEntityIterCBType m_cbControllableEntityIter
Callback for iterating over entities from within the loop functions.
CMedium::TVector * m_ptMedia
A pointer to the list of media.
virtual void AddControllableEntity(CControllableEntity &c_entity)
std::function< void(CControllableEntity *)> TControllableEntityIterCBType
The callback type for iteration over controllable entities within the PreStep() and/or PostStep() par...
virtual void RemoveControllableEntity(CControllableEntity &c_entity)
pthread_mutex_t * SenseControlStepConditionalMutex
pthread_mutex_t * EntityIterConditionalMutex
pthread_mutex_t * PhysicsConditionalMutex
pthread_mutex_t * ActConditionalMutex
pthread_mutex_t * MediaConditionalMutex
virtual void UpdateMedia()
CSpaceMultiThreadBalanceQuantity()
virtual void UpdateControllableEntitiesAct()
virtual void AddControllableEntity(CControllableEntity &c_entity)
virtual void UpdatePhysics()
virtual void Destroy()
Destroys the space and all its entities.
virtual void UpdateControllableEntitiesSenseStep()
virtual void Init(TConfigurationNode &t_tree)
Initializes the space using the <arena> section of the XML configuration file.
friend void * LaunchUpdateThreadBalanceQuantity(void *p_data)
virtual void IterateOverControllableEntities(const TControllableEntityIterCBType &c_cb)
Given a callback specified in the loop functions, iterate over all controllable entities currently pr...
virtual void RemoveControllableEntity(CControllableEntity &c_entity)
void CollectThreadResourceUsage()