1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33 // Constructor for threadHandler
35 threadHandler<T>::threadHandler
38 const multiThreader& threader
44 nThreads_(threader.getNumThreads()),
45 pthreadID_(pthread_self()),
51 // * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * //
54 threadHandler<T>::~threadHandler()
56 // Null the argument list pointer copies
57 // to avoid multiple deallocations.
58 forAll(argList_, indexI)
60 argList_[indexI] = NULL;
65 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
67 // Return a reference to the template class
69 inline T& threadHandler<T>::reference()
75 // Set a size for the argument list
77 inline void threadHandler<T>::setSize
82 argList_.setSize(size, NULL);
86 // Set a argument pointer for a particular index
88 inline void threadHandler<T>::set
96 FatalErrorIn("threadHandler<T>::set")
97 << "Attempt to access element from zero sized list"
101 if (index < 0 || index >= argList_.size())
103 FatalErrorIn("threadHandler<T>::set")
104 << "index " << index << " out of range 0 ... "
106 << abort(FatalError);
109 argList_[index] = argPtr;
113 // Return a reference to the multiThreader
115 inline const multiThreader& threadHandler<T>::threader() const
121 // Return the number of threads
123 inline label threadHandler<T>::nThreads() const
129 // Designate as master thread
131 inline void threadHandler<T>::setMaster() const
137 // Designate as slave thread
139 inline void threadHandler<T>::setSlave() const
145 // Is this a master thread?
147 inline bool threadHandler<T>::master() const
149 return (master_ == true);
153 // Is this a slave thread?
155 inline bool threadHandler<T>::slave() const
163 inline void threadHandler<T>::lock
165 const signalType sType
180 // Unlock this thread
182 inline void threadHandler<T>::unlock
184 const signalType sType
189 startMutex_.unlock();
199 // Send signal to a waiting conditional
201 inline void threadHandler<T>::sendSignal
203 const signalType sType
208 if (predicate(sType))
210 InfoIn("threadHandler::sendSignal()")
211 << "Predicate is already set."
216 // Set predicate before signalling
237 FatalErrorIn("threadHandler::sendSignal()")
238 << "Undefined enumerant."
239 << abort(FatalError);
248 inline void threadHandler<T>::waitForSignal
250 const signalType sType
255 threader().waitForCondition
264 threader().waitForCondition
272 FatalErrorIn("threadHandler::waitForSignal()")
273 << "Undefined enumerant."
274 << abort(FatalError);
277 if (!predicate(sType))
279 FatalErrorIn("threadHandler::waitForSignal()")
280 << "Spurious wake-up."
281 << abort(FatalError);
284 unsetPredicate(sType);
286 // Unlock the acquired mutex
291 // Return state of the predicate variable
293 inline bool threadHandler<T>::predicate
295 const signalType sType
298 return predicate_[sType];
302 // Set the predicate variable
304 inline void threadHandler<T>::setPredicate
306 const signalType sType
309 predicate_[sType] = true;
313 // Unset the predicate variable
315 inline void threadHandler<T>::unsetPredicate
317 const signalType sType
320 predicate_[sType] = false;
326 inline void threadHandler<T>::setID(const pthread_t& pt)
334 inline pthread_t threadHandler<T>::ID() const
340 // Does the calling thread correspond to this handler?
342 inline bool threadHandler<T>::self() const
344 return pthread_equal(ID(), pthread_self());
348 // Return an argument pointer at a particular index
350 inline void * threadHandler<T>::operator()
355 if (!argList_.size())
357 FatalErrorIn("threadHandler<T>::operator()")
358 << "Attempt to access element from zero sized list"
359 << abort(FatalError);
362 if (index < 0 || index >= argList_.size())
364 FatalErrorIn("threadHandler<T>::operator()")
365 << "index " << index << " out of range 0 ... "
367 << abort(FatalError);
370 if (!argList_[index])
372 FatalErrorIn("threadHandler<T>::operator()")
373 << "Hanging pointer. This is not allowed."
374 << abort(FatalError);
377 return argList_[index];
381 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
383 // Lock all threads provided by sequence
387 const List<label>& sequence,
388 const PtrList<threadHandler<T> >& handler
393 handler[sequence[i]].lock(threadHandler<T>::START);
394 handler[sequence[i]].lock(threadHandler<T>::STOP);
396 handler[sequence[i]].unsetPredicate(threadHandler<T>::START);
397 handler[sequence[i]].unsetPredicate(threadHandler<T>::STOP);
402 // Synchronize all threads provided by sequence
404 void synchronizeThreads
406 const List<label>& sequence,
407 const PtrList<threadHandler<T> >& handler
412 // Wait for a signal from this thread before moving on.
413 handler[sequence[i]].waitForSignal(threadHandler<T>::STOP);
418 // Execute threads for the submitted static function by sequence
422 const List<label>& sequence,
423 PtrList<threadHandler<T> >& handler,
424 void (*tFunction)(void*)
432 "template <class T>\n"
433 "void executeThreads\n"
435 " const List<label>& sequence,\n"
436 " PtrList<threadHandler<T> >& handler,\n"
437 " void (*tFunction)(void*)\n"
440 << "Empty handler list."
441 << abort(FatalError);
444 // Fetch threader reference
445 const multiThreader& threader = handler[0].threader();
447 // Lock slave threads by sequence
448 lockThreads(sequence, handler);
452 // Submit jobs to the work queue
453 threader.addToWorkQueue(tFunction, &(handler[sequence[i]]));
455 // Wait for a signal from this thread before moving on.
456 handler[sequence[i]].waitForSignal(threadHandler<T>::START);
459 // Synchronize threads
460 synchronizeThreads(sequence, handler);
463 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
465 } // End namespace Foam
467 // ************************************************************************* //