44 #define SCHEDULER_HPP 1
53 #include "comptime.hpp"
86 template <
class Solv,
class Prob,
class Err>
106 void *consumer_main(
void ) {
109 #ifdef SCHEDULER_DEBUG
110 std::cout <<
"Consumer main entrance\n";
118 while( (p = _scheduler->get_next_problem( pi )) ) {
128 _scheduler->on_error( e, pi );
131 _scheduler->inc_solved_problem();
134 #ifdef SCHEDULER_DEBUG
135 std::cout <<
"Exiting consumer\n";
145 static void *consumer_entry(
void *data ) {
147 return( consumer->consumer_main() );
150 Consumer( Solv *solver,
Scheduler *scheduler ) : _solver(solver), _scheduler(scheduler) {
153 #ifdef SCHEDULER_DEBUG
154 std::cout <<
"Consumer constructor\n";
161 #ifdef SCHEDULER_DEBUG
162 std::cout <<
"Consumer destructor\n";
175 pthread_create( &_thread, NULL, consumer_entry, (
void *)
this );
180 #ifdef SCHEDULER_DEBUG
181 std::cout <<
"Consumer join\n";
191 pthread_join( _thread, NULL );
197 pthread_mutex_t _mutex;
198 pthread_cond_t _scheduler_cond;
199 pthread_cond_t _producer_cond;
200 pthread_cond_t _consumer_cond;
208 std::vector<Prob *> &_problems;
210 pthread_t _scheduler_thread;
211 std::vector<Consumer *> _consumers;
218 std::vector<Err> _err;
219 std::vector<int32_t> _eprob;
228 void on_error( Err &e, uint32_t pi ) {
229 pthread_mutex_lock( &_mutex );
231 _eprob.push_back( pi );
233 pthread_cond_broadcast( &_scheduler_cond );
234 pthread_mutex_unlock( &_mutex );
240 void inc_solved_problem(
void ) {
241 pthread_mutex_lock( &_mutex );
243 pthread_mutex_unlock( &_mutex );
252 Prob *get_next_problem( uint32_t &pi ) {
253 #ifdef SCHEDULER_DEBUG
254 std::cout <<
"get_next_problem()\n";
256 pthread_mutex_lock( &_mutex );
258 if( _done || _error ) {
259 pthread_mutex_unlock( &_mutex );
260 #ifdef SCHEDULER_DEBUG
261 std::cout <<
"get_next_problem(): Returning NULL\n";
267 if( _problems.size() == _read_c ) {
268 #ifdef SCHEDULER_DEBUG
269 std::cout <<
"get_next_problem(): No problem to return... waiting\n";
272 pthread_cond_signal( &_scheduler_cond );
273 while( _problems.size() == _read_c ) {
275 pthread_cond_wait( &_consumer_cond, &_mutex );
276 if( _done || _error ) {
277 pthread_mutex_unlock( &_mutex );
278 #ifdef SCHEDULER_DEBUG
279 std::cout <<
"get_next_problem(): Returning NULL\n";
289 Prob *ret = _problems[pi];
291 #ifdef SCHEDULER_DEBUG
292 std::cout <<
"get_next_problem(): Returning problem " << pi <<
"\n";
295 pthread_mutex_unlock( &_mutex );
302 void *scheduler_main(
void ) {
304 #ifdef SCHEDULER_DEBUG
305 std::cout <<
"Running scheduler_main()\n";
309 for(
size_t a = 0; a < _consumers.size(); a++ )
310 _consumers[a]->
run();
312 pthread_mutex_lock( &_mutex );
316 while( !(_problems.size() == _solved_c || _done || _error) ) {
318 pthread_cond_wait( &_scheduler_cond, &_mutex );
321 if( (_finish && _problems.size() == _solved_c) || _done || _error )
325 pthread_cond_wait( &_scheduler_cond, &_mutex );
331 pthread_cond_broadcast( &_consumer_cond );
337 pthread_cond_broadcast( &_consumer_cond );
338 pthread_mutex_unlock( &_mutex );
342 for(
size_t a = 0; a < _consumers.size(); a++ )
343 _consumers[a]->join();
345 pthread_cond_broadcast( &_producer_cond );
353 static void *scheduler_entry(
void *data ) {
355 return( scheduler->scheduler_main() );
367 : _read_c(0), _solved_c(0), _problems(prob), _join(false), _running(false),
368 _error(false), _done(false), _finish(false) {
371 pthread_mutex_init( &_mutex, NULL );
372 pthread_cond_init( &_scheduler_cond, NULL );
373 pthread_cond_init( &_consumer_cond, NULL );
374 pthread_cond_init( &_producer_cond, NULL );
386 pthread_mutex_destroy( &_mutex );
387 pthread_cond_destroy( &_scheduler_cond );
388 pthread_cond_destroy( &_consumer_cond );
389 pthread_cond_destroy( &_producer_cond );
412 pthread_mutex_lock( &_mutex );
413 uint32_t ret = _solved_c;
414 pthread_mutex_unlock( &_mutex );
422 pthread_mutex_lock( &_mutex );
423 uint32_t ret = _problems.size();
424 pthread_mutex_unlock( &_mutex );
437 template <
class Cont1,
class Cont2>
439 pthread_mutex_lock( &_mutex );
440 size_t r = _err.size();
441 for(
size_t a = 0; a < _err.size(); a++ ) {
442 e.push_back( _err[a] );
443 pi.push_back( _eprob[a] );
447 pthread_mutex_unlock( &_mutex );
458 void run( std::vector<Solv *> solv ) {
465 for(
size_t a = 0; a < solv.size(); a++ )
466 _consumers.push_back(
new Consumer( solv[a],
this ) );
479 pthread_create( &_scheduler_thread, NULL, scheduler_entry, (
void *)
this );
487 pthread_mutex_lock( &_mutex );
495 pthread_cond_broadcast( &_scheduler_cond );
496 pthread_mutex_unlock( &_mutex );
521 pthread_mutex_lock( &_mutex );
524 pthread_cond_broadcast( &_scheduler_cond );
527 ibs_clock_gettime( CLOCK_REALTIME, &ts );
529 int rc = pthread_cond_timedwait( &_producer_cond, &_mutex, &ts );
530 if( rc == ETIMEDOUT ) {
531 pthread_mutex_unlock( &_mutex );
535 pthread_mutex_unlock( &_mutex );
549 pthread_mutex_lock( &_mutex );
553 pthread_cond_broadcast( &_scheduler_cond );
556 pthread_cond_wait( &_producer_cond, &_mutex );
558 pthread_mutex_unlock( &_mutex );
562 for(
size_t a = 0; a < _consumers.size(); a++ )
563 delete _consumers[a];
566 pthread_join( _scheduler_thread, NULL );