medfall

A super great game engine
Log | Files | Refs

context_bound_scheduler.hpp (4774B)


      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_CONTEXT_BOUND_SCHEDULER_HPP
     11 #define RL_CONTEXT_BOUND_SCHEDULER_HPP
     12 #ifdef _MSC_VER
     13 #   pragma once
     14 #endif
     15 
     16 #include "base.hpp"
     17 #include "full_search_scheduler.hpp"
     18 #include "foreach.hpp"
     19 
     20 
     21 namespace rl
     22 {
     23 
     24 
     25 template<thread_id_t thread_count>
     26 struct context_bound_scheduler_thread_info : tree_search_scheduler_thread_info<thread_count>
     27 {
     28     unsigned sched_count_;
     29     unsigned forced_context_switch_count_;
     30 
     31     void reset(test_params& params)
     32     {
     33         tree_search_scheduler_thread_info<thread_count>::reset(params);
     34         sched_count_ = 0;
     35         forced_context_switch_count_ = 0;
     36     }
     37 };
     38 
     39 
     40 
     41 
     42 template<thread_id_t thread_count>
     43 class context_bound_scheduler
     44     : public tree_search_scheduler<context_bound_scheduler<thread_count>
     45         , context_bound_scheduler_thread_info<thread_count>, thread_count>
     46 {
     47 public:
     48     typedef tree_search_scheduler<context_bound_scheduler<thread_count>
     49         , context_bound_scheduler_thread_info<thread_count>, thread_count> base_t;
     50     typedef typename base_t::thread_info_t thread_info_t;
     51     typedef typename base_t::shared_context_t shared_context_t;
     52 
     53     context_bound_scheduler(test_params& params, shared_context_t& ctx, thread_id_t dynamic_thread_count)
     54         : base_t(params, ctx, dynamic_thread_count)
     55     {
     56     }
     57 
     58     thread_id_t iteration_begin_impl()
     59     {
     60         switches_remain_ = this->params_.context_bound;
     61         return base_t::iteration_begin_impl();
     62     }
     63 
     64     bool can_switch(thread_info_t& t)
     65     {
     66         t.sched_count_ += 1;
     67         return switches_remain_ != 0;
     68     }
     69 
     70     void on_switch(thread_info_t& t)
     71     {
     72         if (t.state_ == thread_state_running)
     73         {
     74             RL_VERIFY(switches_remain_);
     75             switches_remain_ -= 1;
     76         }
     77         else
     78         {
     79             t.forced_context_switch_count_ += 1;
     80         }
     81     }
     82 
     83     double iteration_count_approx()
     84     {
     85         return 1.0;
     86         /*
     87         iteration_t const P = thread_count;
     88         iteration_t const C0 = this->params_.context_bound;
     89         iteration_t total = 1;//factorial(P);// * power(P, P * C0);
     90         for (iteration_t i = 0; i != P - 1; ++i)
     91             total *= power(i + 1, C0 + 1);
     92         //if (C0)
     93         //    total *= power(P - 1, P - 1);
     94         if (val(P) > 1)
     95         {
     96             for (iteration_t i = 0; i != P; ++i)
     97             {
     98                 iteration_t const N = this->threads_[i].sched_count_;
     99                 iteration_t const C = C0 + this->threads_[i].forced_context_switch_count_;
    100                 //total *= (iteration_t)pow((double)(threads_[i].sched_count_ + 2) * (thread_count - 1), (int)(params_.context_bound + threads_[i].forced_context_switch_count_));
    101                 total *= factorial(N, C) / factorial(C);
    102                 //C$ += C + 1;
    103                 //total *= (int)(params_.context_bound + threads_[i].forced_context_switch_count_));
    104             }
    105             //total *= factorial(C$);
    106         }
    107         else
    108         {
    109             total = 1;
    110         }
    111         //iteration_t total = (iteration_t)pow((double)sched_count / thread_count + 1, (int)(params_.context_bound * thread_count + forced_context_switch_mean_ + 0.5));
    112         //total *= thread_count;
    113         //total *= (iteration_t)pow((double)thread_count - 1, thread_count);
    114         for (size_t i = 0; i != this->stree_.size(); ++i)
    115         {
    116             if (this->stree_[i].type_ != sched_type_sched)
    117             {
    118                 total *= this->stree_[i].count_;
    119             }
    120         }
    121         return (double)total;
    122         */
    123     }
    124 
    125 private:
    126     unsigned switches_remain_;
    127 
    128     template<typename T>
    129     static T factorial(T x, T i)
    130     {
    131         if (0 == i)
    132             return 1;
    133         T r = x;
    134         for (--i; i; --i)
    135             r *= x - i;
    136         return r;
    137     }
    138 
    139     template<typename T>
    140     static T factorial(T x)
    141     {
    142         if (0 == x)
    143             return 1;
    144         T r = x;
    145         for (T i = x - 1; i; --i)
    146             r *= i;
    147         return r;
    148     }
    149 
    150     template<typename T>
    151     static T power(T x, T y)
    152     {
    153         if (0 == y)
    154             return 1;
    155         T r = x;
    156         for (T i = y - 1; i; --i)
    157             r *= x;
    158         return r;
    159     }
    160 
    161     RL_NOCOPY(context_bound_scheduler);
    162 };
    163 
    164 
    165 }
    166 
    167 #endif
    168