medfall

A super great game engine
Log | Files | Refs

history.hpp (5080B)


      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_HISTORY_HPP
     11 #define RL_HISTORY_HPP
     12 #ifdef _MSC_VER
     13 #   pragma once
     14 #endif
     15 
     16 #include "base.hpp"
     17 
     18 
     19 namespace rl
     20 {
     21 
     22 
     23 typedef void (*event_output_f)(std::ostream& s, void const* ev);
     24 typedef void (*event_dtor_f)(void* ev);
     25 
     26 struct history_entry
     27 {
     28     thread_id_t thread_index_;
     29     debug_info info_;
     30     void* ev_;
     31     event_output_f output_;
     32     event_dtor_f dtor_;
     33 
     34     history_entry(thread_id_t thread_index, debug_info_param info, void* ev, event_output_f output, event_dtor_f dtor)
     35         : thread_index_(thread_index)
     36         , info_(info)
     37         , ev_(ev)
     38         , output_(output)
     39         , dtor_(dtor)
     40     {
     41     }
     42 };
     43 
     44 template<typename T>
     45 void event_output(std::ostream& s, void const* ev)
     46 {
     47     static_cast<T const*>(ev)->output(s);
     48 }
     49 
     50 template<typename T>
     51 void event_dtor(void* ev)
     52 {
     53     delete static_cast<T*>(ev);
     54 }
     55 
     56 
     57 struct user_event
     58 {
     59     char const* desc_;
     60 
     61     void output(std::ostream& s) const
     62     {
     63         s << desc_;
     64     }
     65 };
     66 
     67 inline string strip_path(char const* filename)
     68 {
     69     char const* slash = strrchr(filename, '\\');
     70     if (slash)
     71         return slash + 1;
     72     else
     73         return filename;
     74 }
     75 
     76 inline std::ostream& operator << (std::ostream& ss, debug_info_param info)
     77 {
     78     /*
     79     char const* func = info;
     80     char const* file = info + strlen(info) + 1;
     81     char const* line = file + strlen(file) + 1;
     82     */
     83 
     84 #ifdef RL_MSVC_OUTPUT
     85     ss << info.file_ << "(" << info.line_ << ") : ";
     86 #else
     87     ss << info.func_ << ", " << strip_path(info.file_) << "(" << info.line_ << ")";
     88 #endif
     89     return ss;
     90 }
     91 
     92 
     93 
     94 class history_mgr : nocopy<>
     95 {
     96 public:
     97     history_mgr(std::ostream& stream, thread_id_t thread_count)
     98         : thread_count_(thread_count)
     99         , out_stream_(stream)
    100     {
    101     }
    102 
    103     ~history_mgr()
    104     {
    105         clear();
    106     }
    107 
    108     template<typename event_t>
    109     void exec_log(thread_id_t th, debug_info_param info, event_t const& ev, bool output_history)
    110     {
    111         exec_history_.push_back(history_entry(th, info, new event_t(ev), &event_output<event_t>, &event_dtor<event_t>));
    112         if (output_history)
    113         {
    114             output(exec_history_.size() - 1);
    115         }
    116     }
    117 
    118     void print_exec_history(bool output_history)
    119     {
    120         size_t const buf_size = 4096;
    121         char buf [buf_size + 1];
    122 
    123         size_t const count = exec_history_.size();
    124         if (false == output_history)
    125         {
    126             sprintf(buf, "execution history (%u):\n", (unsigned)count);
    127             out_stream_ << buf;
    128 #if defined(_MSC_VER) && defined(RL_MSVC_OUTPUT)
    129             OutputDebugStringA(buf);
    130 #endif
    131 
    132             for (size_t i = 0; i != count; ++i)
    133             {
    134                 output(i);
    135             }
    136         }
    137         out_stream_ << "\n";
    138 #if defined(_MSC_VER) && defined(RL_MSVC_OUTPUT)
    139         OutputDebugStringA("\n");
    140 #endif
    141 
    142         for (thread_id_t th = 0; th != thread_count_; ++th)
    143         {
    144             sprintf(buf, "thread %u:\n", th);
    145             out_stream_ << buf;
    146 #if defined(_MSC_VER) && defined(RL_MSVC_OUTPUT)
    147             OutputDebugStringA(buf);
    148 #endif
    149             for (size_t i = 0; i != count; ++i)
    150             {
    151                 if (exec_history_[i].thread_index_ == th)
    152                 {
    153                     output(i);
    154                 }
    155             }
    156             out_stream_ << "\n";
    157 #if defined(_MSC_VER) && defined(RL_MSVC_OUTPUT)
    158             OutputDebugStringA("\n");
    159 #endif
    160         }
    161     }
    162 
    163     void clear()
    164     {
    165         for (size_t i = 0; i != exec_history_.size(); ++i)
    166         {
    167             history_entry const& ent = exec_history_[i];
    168             ent.dtor_(ent.ev_);
    169         }
    170         exec_history_.clear();
    171     }
    172 
    173 private:
    174     vector<history_entry>::type exec_history_;
    175     thread_id_t                 thread_count_;
    176     std::ostream&               out_stream_;
    177 
    178     void output(size_t i)
    179     {
    180         std::basic_ostringstream<char, std::char_traits<char>, raw_allocator<char> > stream;
    181 
    182         history_entry const& ent = exec_history_[i];
    183 #ifdef RL_MSVC_OUTPUT
    184         {
    185             stream << ent.info_ << "[" << i << "] " << ent.thread_index_ << ": ";
    186             ent.output_(stream, ent.ev_);
    187             stream << std::endl;
    188         }
    189 #else
    190         stream << "[" << (unsigned)i << "] " << ent.thread_index_ << ": ";
    191         ent.output_(stream, ent.ev_);
    192         stream << ", in " << ent.info_ << std::endl;
    193 #endif
    194 
    195         out_stream_ << stream.str();
    196 #if defined(_MSC_VER) && defined(RL_MSVC_OUTPUT)
    197         OutputDebugStringA(stream.str().c_str());
    198 #endif
    199     }
    200 };
    201 
    202 
    203 }
    204 
    205 #endif