Scroom  0.14
threadpool-tests.cc File Reference
#include <scroom/threadpool.hh>
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/thread.hpp>
#include <scroom/function-additor.hh>
#include <scroom/semaphore.hh>
#include "helpers.hh"
Include dependency graph for threadpool-tests.cc:

Classes

class  A
 
class  B< R >
 

Functions

const millisec short_timeout (250)
 
const millisec long_timeout (2000)
 
template<typename R >
no_op (Semaphore *s, R result)
 
bool has_at_least_n_threads (ThreadPool *pool, int count_)
 
bool has_exactly_n_threads (ThreadPool *pool, int count)
 
 BOOST_AUTO_TEST_CASE (work_gets_done)
 
 BOOST_AUTO_TEST_CASE (work_gets_done_by_prio)
 
 BOOST_AUTO_TEST_CASE (construct_0_threads)
 
 BOOST_AUTO_TEST_CASE (construct_1_threads)
 
 BOOST_AUTO_TEST_CASE (construct_2_threads)
 
 BOOST_AUTO_TEST_CASE (schedule_shared_pointer)
 
 BOOST_AUTO_TEST_CASE (schedule_future)
 
 BOOST_AUTO_TEST_CASE (schedule_shared_pointer_with_future)
 
 BOOST_AUTO_TEST_CASE (verify_threadcount)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/9]

BOOST_AUTO_TEST_CASE ( construct_0_threads  )
171 {
172  ThreadPool pool(0);
173  BOOST_CHECK(has_exactly_n_threads(&pool, 0));
174 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [2/9]

BOOST_AUTO_TEST_CASE ( construct_1_threads  )
177 {
178  ThreadPool pool(1);
179  BOOST_CHECK(has_exactly_n_threads(&pool, 1));
180 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [3/9]

BOOST_AUTO_TEST_CASE ( construct_2_threads  )
183 {
184  ThreadPool pool(2);
185  const int expected = 2;
186 #ifndef MULTITHREADING
187  expected = 1;
188 #endif
189  BOOST_CHECK(has_exactly_n_threads(&pool, expected));
190 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [4/9]

BOOST_AUTO_TEST_CASE ( schedule_future  )
202 {
203  ThreadPool pool(0);
204  Semaphore a(0);
205 
206  boost::unique_future<int> result(pool.schedule<int>(boost::bind(no_op<int>, &a, 42)));
207 
208  BOOST_CHECK(!a.P(short_timeout));
209  BOOST_CHECK(!result.is_ready());
210  pool.add();
211 
212  BOOST_CHECK(a.P(long_timeout));
213  BOOST_CHECK_EQUAL(42, result.get());
214 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [5/9]

BOOST_AUTO_TEST_CASE ( schedule_shared_pointer  )
193 {
194  ThreadPool pool(1);
195  Semaphore a(0);
196 
197  pool.schedule(A::create(&a));
198  BOOST_CHECK(a.P(long_timeout));
199 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [6/9]

BOOST_AUTO_TEST_CASE ( schedule_shared_pointer_with_future  )
217 {
218  ThreadPool pool(0);
219  Semaphore a(0);
220 
221  boost::unique_future<bool> result(pool.schedule<bool, B<bool>>(B<bool>::create(&a, false)));
222 
223  BOOST_CHECK(!a.P(short_timeout));
224  BOOST_CHECK(!result.is_ready());
225  pool.add();
226 
227  BOOST_CHECK(a.P(long_timeout));
228  BOOST_CHECK_EQUAL(false, result.get());
229 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [7/9]

BOOST_AUTO_TEST_CASE ( verify_threadcount  )
238 {
239  ThreadPool::Ptr const t = CpuBound();
240  const int expected = boost::thread::hardware_concurrency();
241 #ifndef MULTITHREADING
242  expected = 1;
243 #endif
244  BOOST_CHECK(has_exactly_n_threads(t.get(), expected));
245 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [8/9]

BOOST_AUTO_TEST_CASE ( work_gets_done  )
138 {
139  Semaphore s(0);
140  ThreadPool pool(0);
141  pool.schedule(clear(&s));
142 
143  // Work doesn't get done with no threads
144  BOOST_CHECK(!s.P(long_timeout));
145  pool.add();
146 
147  // With a thread, work gets done
148  BOOST_CHECK(s.P(long_timeout));
149 }
Here is the call graph for this function:

◆ BOOST_AUTO_TEST_CASE() [9/9]

BOOST_AUTO_TEST_CASE ( work_gets_done_by_prio  )
152 {
153  Semaphore high(0);
154  Semaphore low(0);
155  ThreadPool pool(0);
156  pool.schedule(clear(&low), PRIO_NORMAL);
157  pool.schedule(pass(&low) + clear(&high), PRIO_HIGH);
158 
159  pool.add();
160  // Thread is doing the high-prio tasks first, which is blocked on
161  // the low semaphore, hence, no work gets done.
162  BOOST_CHECK(!high.P(short_timeout));
163 
164  pool.add();
165  // Second thread does the low-prio task, which unblocks the
166  // high-prio one. How's that for priority inversion :-)
167  BOOST_CHECK(high.P(long_timeout));
168 }
Here is the call graph for this function:

◆ has_at_least_n_threads()

bool has_at_least_n_threads ( ThreadPool pool,
int  count_ 
)
87 {
88  if(count_ <= 0)
89  {
90  return true;
91  }
92 
93  std::vector<Semaphore*> semaphores(count_);
94  for(int i = 0; i < count_; i++)
95  {
96  semaphores[i] = new Semaphore(0);
97  }
98 
99  for(int i = 0; i < count_ - 1; i++)
100  {
101  pool->schedule(pass(semaphores[i + 1]) + clear(semaphores[i]));
102  }
103 
104  // All tasks are blocked on semaphores[count-1]
105 
106  pool->schedule(clear(semaphores[count_ - 1]));
107  // If jobs of the same priority are scheduled in order, and if
108  // there are at least count_ threads, then this final job will get
109  // scheduled on the last available thread, thus freeing all
110  // others.
111  bool const result = semaphores[0]->P(long_timeout);
112 
113  if(!result)
114  {
115  // If there are too few threads, then all threads are still
116  // blocked. This will ultimately block the ThreadPool destructor,
117  // so we have to unblock them manually here.
118  for(int i = 1; i < count_; i++)
119  {
120  semaphores[i]->V();
121  }
122  }
123  return result;
124 }

Referenced by has_exactly_n_threads().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_exactly_n_threads()

bool has_exactly_n_threads ( ThreadPool pool,
int  count 
)
127 {
128  return has_at_least_n_threads(pool, count) && !has_at_least_n_threads(pool, count + 1);
129 }

Referenced by BOOST_AUTO_TEST_CASE().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ long_timeout()

const millisec long_timeout ( 2000  )

Referenced by BOOST_AUTO_TEST_CASE(), and has_at_least_n_threads().

Here is the caller graph for this function:

◆ no_op()

template<typename R >
R no_op ( Semaphore s,
result 
)
79 {
80  s->V();
81  return result;
82 }
Here is the call graph for this function:

◆ short_timeout()

const millisec short_timeout ( 250  )

Referenced by BOOST_AUTO_TEST_CASE().

Here is the caller graph for this function:
ThreadPool::Ptr
boost::shared_ptr< ThreadPool > Ptr
Definition: threadpool.hh:169
long_timeout
const millisec long_timeout(2000)
clear
boost::function< void()> clear(Semaphore *s)
Definition: helpers.cc:29
has_exactly_n_threads
bool has_exactly_n_threads(ThreadPool *pool, int count)
Definition: threadpool-tests.cc:126
ThreadPool
Definition: threadpool.hh:46
short_timeout
const millisec short_timeout(250)
BOOST_CHECK_EQUAL
BOOST_CHECK_EQUAL(sample.expectedColors, originalColormap->colors.size())
CpuBound
ThreadPool::Ptr CpuBound()
Definition: threadpoolimpl.cc:452
Scroom::Semaphore
Definition: semaphore.hh:15
PRIO_HIGH
@ PRIO_HIGH
Definition: threadpool.hh:28
pass
boost::function< void()> pass(Semaphore *s)
Definition: helpers.cc:27
A::create
static Ptr create(int &i)
Definition: boost-bind.cc:38
Scroom::Semaphore::V
void V()
Definition: semaphore.hh:77
PRIO_NORMAL
@ PRIO_NORMAL
Definition: threadpool.hh:29
ThreadPool::schedule
void schedule(boost::function< void()> const &fn, int priority=defaultPriority, const Queue::Ptr &queue=defaultQueue())
Definition: threadpoolimpl.cc:342
has_at_least_n_threads
bool has_at_least_n_threads(ThreadPool *pool, int count_)
Definition: threadpool-tests.cc:86
B
Definition: threadpool-tests.cc:53