2 #ifndef ROSE_ParallelSort_H
3 #define ROSE_ParallelSort_H
5 #include <boost/thread.hpp>
21 namespace ParallelSort {
27 template<
class RandomAccessIterator>
29 RandomAccessIterator begin, end;
30 Work(RandomAccessIterator begin, RandomAccessIterator end): begin(begin), end(end) {}
34 template<
class RandomAccessIterator,
class Compare>
37 boost::condition_variable worklistInsertion;
38 static const int multiThreshold = 10000;
40 std::list<Work<RandomAccessIterator> > worklist;
42 Job(Compare compare): compare(compare), npending(0) {}
49 template<
class RandomAccessIterator,
class Compare>
50 RandomAccessIterator partition(RandomAccessIterator begin, RandomAccessIterator end,
51 RandomAccessIterator pivot, Compare compare) {
53 assert(pivot >= begin && pivot < end);
54 std::swap(*pivot, *(end-1));
55 for (RandomAccessIterator i=pivot=begin; i+1<end; ++i) {
56 if (compare(*i, *(end-1)))
57 std::swap(*i, *pivot++);
59 std::swap(*(end-1), *pivot);
64 template<
class RandomAccessIterator,
class Compare>
65 void addWork(Job<RandomAccessIterator, Compare> &job,
const Work<RandomAccessIterator> &work) {
66 boost::lock_guard<boost::mutex> lock(job.mutex);
67 job.worklist.push_back(work);
68 job.worklistInsertion.notify_one();
72 template<
class RandomAccessIterator,
class Compare>
73 void quicksort(Job<RandomAccessIterator, Compare> &job, Work<RandomAccessIterator> work) {
74 while (work.end - work.begin > 1) {
75 if (work.end - work.begin < job.multiThreshold) {
76 std::sort(work.begin, work.end, job.compare);
79 RandomAccessIterator pivot = work.begin + (work.end - work.begin) / 2;
80 pivot = partition(work.begin, work.end, pivot, job.compare);
81 addWork(job, Work<RandomAccessIterator>(pivot+1, work.end));
88 template<
class RandomAccessIterator,
class Compare>
94 boost::unique_lock<boost::mutex> lock(job.mutex);
97 while (job.worklist.empty() && job.npending>0)
98 job.worklistInsertion.wait(lock);
99 if (job.worklist.empty())
102 job.worklist.pop_front();
111 assert(job.npending>0);
112 if (0==--job.npending && job.worklist.empty())
113 job.worklistInsertion.notify_all();
139 template<
class RandomAccessIterator,
class Compare>
140 void quicksort(RandomAccessIterator begin, RandomAccessIterator end, Compare compare,
size_t nthreads) {
142 using namespace Private;
144 Job<RandomAccessIterator, Compare> job(compare);
145 addWork(job, Work<RandomAccessIterator>(begin, end));
148 size_t nworkers = std::max(nthreads, (
size_t)1) - 1;
149 boost::thread *workers =
new boost::thread[nworkers];
150 for (
size_t i=0; i<nworkers; ++i)
151 workers[i] = boost::thread(Worker<RandomAccessIterator, Compare>(job, i+1));
154 Worker<RandomAccessIterator, Compare>(job, 0)();
157 for (
size_t i=0; i<nworkers; ++i)