X-Git-Url: https://ruin.nu/git/?a=blobdiff_plain;f=src%2Fthreadgenesorter.cpp;fp=src%2Fthreadgenesorter.cpp;h=a45988c21dcc4a14f7717a9ef7b07d9757f81179;hb=623097444fac1993a86e6d73b203bc3c6d731c11;hp=0000000000000000000000000000000000000000;hpb=69cfdf79b7597ee6133dc3add1a759bc94861fa6;p=germs.git diff --git a/src/threadgenesorter.cpp b/src/threadgenesorter.cpp new file mode 100644 index 0000000..a45988c --- /dev/null +++ b/src/threadgenesorter.cpp @@ -0,0 +1,163 @@ +/*************************************************************************** + * Copyright (C) 2008 by Michael Andreen * + * andreen@student.chalmers.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * + ***************************************************************************/ + +#include "threadgenesorter.h" +#include "sortaction.h" + +using namespace std; + +/** + * Handles locking and unlocking of mutexes. + * + * RAII style class for mutex acquisition. + */ +class Mutex { + pthread_mutex_t* _m; + bool _locked; + public: + Mutex(pthread_mutex_t* m){ + _m = m; + pthread_mutex_lock(_m); + _locked = true; + } + void unlock(){ + pthread_mutex_unlock(_m); + _locked = false; + } + ~Mutex(){ + if (_locked) + unlock(); + } +}; + +struct ExecutionStuff { + ExecutionStuff(ThreadGeneSorter* so, const GeneOrder& go): _sorter(so) + ,_go(go){}; + ThreadGeneSorter* _sorter; + GeneOrder _go; +}; + + +ThreadGeneSorter::ThreadGeneSorter(const Model& m, int threads) : _model(m){ + _workers = threads; + pthread_mutex_init(&_queuelock, NULL); + pthread_mutex_init(&_solutionslock, NULL); + pthread_cond_init(&_addedSolution,NULL); + pthread_cond_init(&_addedTask,NULL); + pthread_cond_init(&_waiting,NULL); +} + +void ThreadGeneSorter::join(){ + pthread_join(_tid,NULL); +} + +void ThreadGeneSorter::stop(){ + _done = true; +} + +size_t ThreadGeneSorter::size(){ + //TODO: thread safety.. + return _solutions.size(); +} + +double progress(int time, int solutions = 1){ +} + +ThreadGeneSorter::SolutionsQueue ThreadGeneSorter::solutions(){ + //TODO: thread safety.. + return _solutions; +} + +void ThreadGeneSorter::start(const GeneOrder& go){ + pthread_attr_t tattr; + pthread_attr_init(&tattr); + pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); + ExecutionStuff* es = new ExecutionStuff(this,go); + pthread_create(&_tid, &tattr, t_sorter, es); +} + +void ThreadGeneSorter::sorter(const GeneOrder& go){ + _queue.push(SortUnit(0.0,go,ActionList())); + pthread_attr_t tattr; + pthread_attr_init(&tattr); + pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM); + _done = false; + _queue = SortQueue(); + _solutions = SolutionsQueue(); + + queue threads; + + _queue.push(SortUnit(0.0,go,ActionList())); + + int workers = _workers; + while (!_done){ + if (workers){ + --workers; + pthread_t tid; + pthread_create(&tid, &tattr, t_worker, this); + threads.push(tid); + }else{ + Mutex m(&_queuelock); + while(_workers != 0 && !_done){ + pthread_cond_wait(&_waiting,&_queuelock); + } + if (_workers == 0) + _done = true; + } + } + pthread_cond_broadcast(&_addedTask); + while(threads.size() > 0){ + pthread_join(threads.front(),NULL); + threads.pop(); + } + pthread_exit((void*)0); +} + +void ThreadGeneSorter::worker(){ + while(!_done){ + Mutex m(&_queuelock); + + while (_queue.size() == 0 && !_done){ + --_workers; + pthread_cond_signal(&_waiting); + pthread_cond_wait(&_addedTask,&_queuelock); + ++_workers; + } + if (_done) + break; + + SortUnit su = _queue.top(); + _queue.pop(); + m.unlock(); + } +} + +void* t_sorter(void* arg){ + ExecutionStuff* es = static_cast(arg); + es->_sorter->sorter(es->_go); + delete es; + pthread_exit((void*)0); +} + +void* t_worker(void* arg){ + ThreadGeneSorter* sorter = static_cast(arg); + sorter->worker(); + pthread_exit((void*)0); +}