示例#1
0
 resumable* dequeue(Worker* self) {
   // we wait for new jobs by polling our external queue: first, we
   // assume an active work load on the machine and perform aggresive
   // polling, then we relax our polling a bit and wait 50 us between
   // dequeue attempts, finally we assume pretty much nothing is going
   // on and poll every 10 ms; this strategy strives to minimize the
   // downside of "busy waiting", which still performs much better than a
   // "signalizing" implementation based on mutexes and conition variables
   auto& strategies = d(self).strategies;
   resumable* job = nullptr;
   for (auto& strat : strategies) {
     for (size_t i = 0; i < strat.attempts; i += strat.step_size) {
       job = d(self).queue.take_head();
       if (job)
         return job;
       // try to steal every X poll attempts
       if ((i % strat.steal_interval) == 0) {
         job = try_steal(self);
         if (job)
           return job;
       }
       if (strat.sleep_duration.count() > 0)
         std::this_thread::sleep_for(strat.sleep_duration);
     }
   }
   // unreachable, because the last strategy loops
   // until a job has been dequeued
   return nullptr;
 }
示例#2
0
static gboolean
dequeue_or_steal (ThreadPool *tp, gpointer *data, MonoWSQ *local_wsq)
{
	if (mono_runtime_is_shutting_down ())
		return FALSE;
	mono_cq_dequeue (tp->queue, (MonoObject **) data);
	if (!tp->is_io && !*data)
		try_steal (local_wsq, data, FALSE);
	return (*data != NULL);
}
 resumable* dequeue(Worker* self) {
   // we wait for new jobs by polling our external queue: first, we
   // assume an active work load on the machine and perform aggresive
   // polling, then we relax our polling a bit and wait 50 us between
   // dequeue attempts, finally we assume pretty much nothing is going
   // on and poll every 10 ms; this strategy strives to minimize the
   // downside of "busy waiting", which still performs much better than a
   // "signalizing" implementation based on mutexes and conition variables
   struct poll_strategy {
     size_t attempts;
     size_t step_size;
     size_t steal_interval;
     std::chrono::microseconds sleep_duration;
   };
   constexpr poll_strategy strategies[3] = {
     // aggressive polling  (100x) without sleep interval
     {100, 1, 10, std::chrono::microseconds{0}},
     // moderate polling (500x) with 50 us sleep interval
     {500, 1, 5,  std::chrono::microseconds{50}},
     // relaxed polling (infinite attempts) with 10 ms sleep interval
     {101, 0, 1,  std::chrono::microseconds{10000}}
   };
   resumable* job = nullptr;
   for (auto& strat : strategies) {
     for (size_t i = 0; i < strat.attempts; i += strat.step_size) {
       job = d(self).queue.take_head();
       if (job) {
         return job;
       }
       // try to steal every X poll attempts
       if ((i % strat.steal_interval) == 0) {
         job = try_steal(self);
         if (job) {
           return job;
         }
       }
       std::this_thread::sleep_for(strat.sleep_duration);
     }
   }
   // unreachable, because the last strategy loops
   // until a job has been dequeued
   return nullptr;
 }