engine.hh gecode/search.hh gecode/search/support.hh gecode/search/worker.hh gecode/search/parallel/path.hh /usr/include/gecode/search/parallel/bab.hh /usr/include/gecode/search/parallel/dfs.hh Gecode::Search::Parallel::Engine Gecode::Search::Parallel::Engine::Worker Gecode Gecode::Search Gecode::Search::Parallel /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *ChristianSchulte<schulte@gecode.org> * *Copyright: *ChristianSchulte,2009 * *Lastmodified: *$Date:2013-07-1112:30:18+0200(Thu,11Jul2013)$by$Author:schulte$ *$Revision:13840$ * *ThisfileispartofGecode,thegenericconstraint *developmentenvironment: *http://www.gecode.org * *Permissionisherebygranted,freeofcharge,toanypersonobtaining *acopyofthissoftwareandassociateddocumentationfiles(the *"Software"),todealintheSoftwarewithoutrestriction,including *withoutlimitationtherightstouse,copy,modify,merge,publish, *distribute,sublicense,and/orsellcopiesoftheSoftware,andto *permitpersonstowhomtheSoftwareisfurnishedtodoso,subjectto *thefollowingconditions: * *Theabovecopyrightnoticeandthispermissionnoticeshallbe *includedinallcopiesorsubstantialportionsoftheSoftware. * *THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND, *EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOF *MERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEAND *NONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERSBE *LIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINANACTION *OFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORINCONNECTION *WITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHESOFTWARE. * */ #ifndef__GECODE_SEARCH_PARALLEL_ENGINE_HH__ #define__GECODE_SEARCH_PARALLEL_ENGINE_HH__ #include<gecode/search.hh> #include<gecode/search/support.hh> #include<gecode/search/worker.hh> #include<gecode/search/parallel/path.hh> namespaceGecode{namespaceSearch{namespaceParallel{ classEngine:publicSearch::Engine{ protected: classWorker:publicSearch::Worker,publicSupport::Runnable{ protected: Engine&_engine; Support::Mutexm; Pathpath; Space*cur; unsignedintd; boolidle; public: Worker(Space*s,Engine&e); Space*steal(unsignedlongint&d); Statisticsstatistics(void); Engine&engine(void)const; NoGoods&nogoods(void); virtual~Worker(void); }; constOptions_opt; public: constOptions&opt(void)const; unsignedintworkers(void)const; enumCmd{ C_WORK, C_WAIT, C_RESET, C_TERMINATE }; protected: volatileCmd_cmd; Support::Mutex_m_wait; public: Cmdcmd(void)const; voidblock(void); voidrelease(Cmdc); voidwait(void); protected: Support::Mutex_m_term; volatileunsignedint_n_term_not_ack; Support::Event_e_term_ack; Support::Mutex_m_wait_terminate; volatileunsignedint_n_not_terminated; Support::Event_e_terminate; public: voidack_terminate(void); voidterminated(void); voidwait_terminate(void); voidterminate(void); protected: Support::Mutex_m_reset; volatileunsignedint_n_reset_not_ack; Support::Evente_reset_ack_start; Support::Evente_reset_ack_stop; Support::Mutexm_wait_reset; public: voidack_reset_start(void); voidack_reset_stop(void); voidwait_reset(void); protected: Support::Mutexm_search; Support::Evente_search; Support::DynamicQueue<Space*,Heap>solutions; volatileunsignedintn_busy; volatileboolhas_stopped; boolsignal(void)const; public: voididle(void); voidbusy(void); voidstop(void); Engine(constOptions&o); virtualSpace*next(void); virtualboolstopped(void)const; }; /* *Basicaccessroutines */ forceinlineEngine& Engine::Worker::engine(void)const{ return_engine; } forceinlineconstOptions& Engine::opt(void)const{ return_opt; } forceinlineunsignedint Engine::workers(void)const{ returnstatic_cast<unsignedint>(opt().threads); } /* *Engine:commandandwaithandling */ forceinlineEngine::Cmd Engine::cmd(void)const{ return_cmd; } forceinlinevoid Engine::block(void){ _cmd=C_WAIT; _m_wait.acquire(); } forceinlinevoid Engine::release(Cmdc){ _cmd=c; _m_wait.release(); } forceinlinevoid Engine::wait(void){ _m_wait.acquire();_m_wait.release(); } /* *Engine:initialization */ forceinline Engine::Worker::Worker(Space*s,Engine&e) :_engine(e), path(s==NULL?0:static_cast<int>(e.opt().nogoods_limit)),d(0), idle(false){ if(s!=NULL){ if(s->status(*this)==SS_FAILED){ fail++; cur=NULL; if(!engine().opt().clone) deletes; }else{ cur=snapshot(s,engine().opt(),false); } }else{ cur=NULL; } } forceinline Engine::Engine(constOptions&o) :_opt(o),solutions(heap){ //Initializeterminationinformation _n_term_not_ack=workers(); _n_not_terminated=workers(); //Initializesearchinformation n_busy=workers(); has_stopped=false; //Initializeresetinformation _n_reset_not_ack=workers(); } /* *Statistics */ forceinlineStatistics Engine::Worker::statistics(void){ m.acquire(); Statisticss=*this; m.release(); returns; } /* *Engine:searchcontrol */ forceinlinebool Engine::signal(void)const{ returnsolutions.empty()&&(n_busy>0)&&!has_stopped; } forceinlinevoid Engine::idle(void){ m_search.acquire(); boolbs=signal(); n_busy--; if(bs&&(n_busy==0)) e_search.signal(); m_search.release(); } forceinlinevoid Engine::busy(void){ m_search.acquire(); assert(n_busy>0); n_busy++; m_search.release(); } forceinlinevoid Engine::stop(void){ m_search.acquire(); boolbs=signal(); has_stopped=true; if(bs) e_search.signal(); m_search.release(); } /* *Engine:terminationcontrol */ forceinlinevoid Engine::terminated(void){ unsignedintn; _m_term.acquire(); n=--_n_not_terminated; _m_term.release(); //Thesignalmustbeoutsideofthelook,otherwiseathreadmightbe //terminatedthatstillholdsamutex. if(n==0) _e_terminate.signal(); } forceinlinevoid Engine::ack_terminate(void){ _m_term.acquire(); if(--_n_term_not_ack==0) _e_term_ack.signal(); _m_term.release(); } forceinlinevoid Engine::wait_terminate(void){ _m_wait_terminate.acquire(); _m_wait_terminate.release(); } forceinlinevoid Engine::terminate(void){ //Grabthewaitmutexfortermination _m_wait_terminate.acquire(); //Releaseallthreads release(C_TERMINATE); //Waituntilallthreadshaveacknowledgedterminationrequest _e_term_ack.wait(); //Releasewaitingthreads _m_wait_terminate.release(); //Waituntilallthreadshaveinfactterminated _e_terminate.wait(); //Nowallthreadsareterminated! } /* *Engine:resetcontrol */ forceinlinevoid Engine::ack_reset_start(void){ _m_reset.acquire(); if(--_n_reset_not_ack==0) e_reset_ack_start.signal(); _m_reset.release(); } forceinlinevoid Engine::ack_reset_stop(void){ _m_reset.acquire(); if(++_n_reset_not_ack==workers()) e_reset_ack_stop.signal(); _m_reset.release(); } forceinlinevoid Engine::wait_reset(void){ m_wait_reset.acquire(); m_wait_reset.release(); } /* *Worker:findingandstealingworking */ forceinlineSpace* Engine::Worker::steal(unsignedlongint&d){ /* *Makeaquickcheckwhethertheworkermighthavework * *Ifthatisnottrueanylonger,theworkerwillbeasked *againeventually. */ if(!path.steal()) returnNULL; m.acquire(); Space*s=path.steal(*this,d); m.release(); //Tellthattherewillbeonemorebusyworker if(s!=NULL) engine().busy(); returns; } /* *ReturnNo-Goods */ forceinlineNoGoods& Engine::Worker::nogoods(void){ returnpath; } }}} #endif //STATISTICS:search-parallel