22namespace ParallelSort {
28template<
class RandomAccessIterator>
30 RandomAccessIterator begin, end;
31 Work(RandomAccessIterator begin, RandomAccessIterator end): begin(begin), end(end) {}
35template<
class RandomAccessIterator,
class Compare>
38 boost::condition_variable worklistInsertion;
39 static const int multiThreshold = 10000;
41 std::list<Work<RandomAccessIterator> > worklist;
43 Job(Compare compare): compare(compare), npending(0) {}
50template<
class RandomAccessIterator,
class Compare>
51RandomAccessIterator partition(RandomAccessIterator begin, RandomAccessIterator end,
52 RandomAccessIterator pivot, Compare compare) {
54 assert(pivot >= begin && pivot < end);
55 std::swap(*pivot, *(end-1));
56 for (RandomAccessIterator i=pivot=begin; i+1<end; ++i) {
57 if (compare(*i, *(end-1)))
58 std::swap(*i, *pivot++);
60 std::swap(*(end-1), *pivot);
65template<
class RandomAccessIterator,
class Compare>
66void addWork(Job<RandomAccessIterator, Compare> &job,
const Work<RandomAccessIterator> &work) {
67 boost::lock_guard<boost::mutex> lock(job.mutex);
68 job.worklist.push_back(work);
69 job.worklistInsertion.notify_one();
73template<
class RandomAccessIterator,
class Compare>
74void quicksort(Job<RandomAccessIterator, Compare> &job, Work<RandomAccessIterator> work) {
75 while (work.end - work.begin > 1) {
76 if (work.end - work.begin < job.multiThreshold) {
77 std::sort(work.begin, work.end, job.compare);
80 RandomAccessIterator pivot = work.begin + (work.end - work.begin) / 2;
81 pivot = partition(work.begin, work.end, pivot, job.compare);
82 addWork(job, Work<RandomAccessIterator>(pivot+1, work.end));
89template<
class RandomAccessIterator,
class Compare>
95 boost::unique_lock<boost::mutex> lock(job.mutex);
98 while (job.worklist.empty() && job.npending>0)
99 job.worklistInsertion.wait(lock);
100 if (job.worklist.empty())
103 job.worklist.pop_front();
108 quicksort(job, work);
112 assert(job.npending>0);
113 if (0==--job.npending && job.worklist.empty())
114 job.worklistInsertion.notify_all();
140template<
class RandomAccessIterator,
class Compare>
141void quicksort(RandomAccessIterator begin, RandomAccessIterator end,
size_t nThreads, Compare compare) {
144 using namespace Private;
146 Job<RandomAccessIterator, Compare> job(compare);
147 addWork(job, Work<RandomAccessIterator>(begin, end));
150 size_t nworkers = std::max(nThreads, (
size_t)1) - 1;
151 boost::thread *workers =
new boost::thread[nworkers];
152 for (
size_t i=0; i<nworkers; ++i)
153 workers[i] = boost::thread(Worker<RandomAccessIterator, Compare>(job, i+1));
156 Worker<RandomAccessIterator, Compare>(job, 0)();
159 for (
size_t i=0; i<nworkers; ++i)