medfall

A super great game engine
Log | Files | Refs

random_scheduler.hpp (4053B)


      1 /*  Relacy Race Detector
      2  *  Copyright (c) 2008-2013, Dmitry S. Vyukov
      3  *  All rights reserved.
      4  *  This software is provided AS-IS with no warranty, either express or implied.
      5  *  This software is distributed under a license and may not be copied,
      6  *  modified or distributed except as expressly authorized under the
      7  *  terms of the license contained in the file LICENSE in this distribution.
      8  */
      9 
     10 #ifndef RL_RANDOM_SCHEDULER_HPP
     11 #define RL_RANDOM_SCHEDULER_HPP
     12 #ifdef _MSC_VER
     13 #   pragma once
     14 #endif
     15 
     16 #include "base.hpp"
     17 #include "scheduler.hpp"
     18 #include "random.hpp"
     19 
     20 
     21 namespace rl
     22 {
     23 
     24 
     25 template<thread_id_t thread_count>
     26 class random_scheduler : public scheduler<random_scheduler<thread_count>, scheduler_thread_info, thread_count>
     27 {
     28 public:
     29     typedef scheduler<random_scheduler<thread_count>, scheduler_thread_info, thread_count> base_t;
     30     typedef typename base_t::thread_info_t thread_info_t;
     31     typedef typename base_t::shared_context_t shared_context_t;
     32 
     33     struct task_t
     34     {
     35     };
     36 
     37     random_scheduler(test_params& params, shared_context_t& ctx, thread_id_t dynamic_thread_count)
     38         : base_t(params, ctx, dynamic_thread_count)
     39     {
     40     }
     41 
     42     thread_id_t iteration_begin_impl()
     43     {
     44         rand_.seed(this->iter_);
     45         unpark_reason reason;
     46         return schedule_impl(reason, false);
     47     }
     48 
     49     bool iteration_end_impl()
     50     {
     51         return this->iter_ == this->params_.iteration_count;
     52     }
     53 
     54     thread_id_t schedule_impl(unpark_reason& reason, unsigned /*yield*/)
     55     {
     56         thread_id_t const running_thread_count = this->running_threads_count;
     57 
     58         thread_id_t timed_thread_count = this->timed_thread_count_;
     59         if (timed_thread_count)
     60         {
     61             thread_id_t cnt = running_thread_count ? timed_thread_count * 4 : timed_thread_count;
     62             thread_id_t idx = rand_.rand() % cnt;
     63             if (idx < timed_thread_count)
     64             {
     65                 thread_info_t* thr = this->timed_threads_[idx];
     66                 thread_id_t th = thr->index_;
     67                 RL_VERIFY(1 == thr->block_count_);
     68                 this->unpark_thread(th);
     69                 RL_VERIFY(thr->state_ == thread_state_running);
     70                 reason = unpark_reason_timeout;
     71                 return th;
     72             }
     73         }
     74 
     75         thread_id_t spurious_thread_count = this->spurious_thread_count_;
     76         if (spurious_thread_count && running_thread_count)
     77         {
     78             thread_id_t cnt = spurious_thread_count * 8;
     79             thread_id_t idx = rand_.rand() % cnt;
     80             if (idx < spurious_thread_count)
     81             {
     82                 thread_info_t* thr = this->spurious_threads_[idx];
     83                 thread_id_t th = thr->index_;
     84                 RL_VERIFY(1 == thr->block_count_);
     85                 this->unpark_thread(th);
     86                 RL_VERIFY(thr->state_ == thread_state_running);
     87                 reason = unpark_reason_spurious;
     88                 return th;
     89             }
     90         }
     91 
     92         RL_VERIFY(running_thread_count);
     93         unsigned index = rand_.rand() % running_thread_count;
     94         thread_id_t th = this->running_threads[index];
     95         reason = unpark_reason_normal;
     96         return th;
     97     }
     98 
     99     unsigned rand_impl(unsigned limit, sched_type t)
    100     {
    101         (void)t;
    102         unsigned r = rand_.rand() % limit;
    103         ///!!!
    104 #ifdef RL_MY_TEST
    105         if (this->iter_ == 8761115)
    106         {
    107             char buf [1024];
    108             sprintf(buf, "rand(%u, %u) = %u\n", t, limit, r);
    109             OutputDebugStringA(buf);
    110         }
    111 #endif
    112         return r;
    113     }
    114 
    115     iteration_t iteration_count_impl()
    116     {
    117         return this->params_.iteration_count;
    118     }
    119 
    120     void get_state_impl(std::ostream& /*ss*/)
    121     {
    122     }
    123 
    124     void set_state_impl(std::istream& /*ss*/)
    125     {
    126     }
    127 
    128     void on_thread_block(thread_id_t /*th*/, bool /*yield*/)
    129     {
    130     }
    131 
    132 private:
    133     random_generator rand_;
    134 
    135     RL_NOCOPY(random_scheduler);
    136 };
    137 
    138 
    139 }
    140 
    141 #endif