File: execution.hpp

package info (click to toggle)
xenium 0.0.2%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,088 kB
  • sloc: cpp: 12,297; makefile: 20
file content (90 lines) | stat: -rw-r--r-- 2,534 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#pragma once

#include "benchmark.hpp"
#include "report.hpp"
#include "workload.hpp"

#include <tao/config/value.hpp>

#include <atomic>
#include <cstdint>
#include <memory>
#include <random>
#include <thread>
#include <vector>

enum class execution_state {
  starting,
  preparing,
  initializing,
  running,
  stopped
};

enum class thread_state {
  starting,
  running,
  ready,
  finished
};

struct initialization_failure : std::exception {
  const char* what() const noexcept override {
    return "Failed to initialize data structure under test-";
  }
};

struct execution;
 
struct execution_thread {
  execution_thread(std::uint32_t id, const execution& exec);
  virtual ~execution_thread() = default;
  virtual void setup(const tao::config::value& config);
  virtual void run() = 0;
  virtual void initialize(std::uint32_t /*num_threads*/) {}
  virtual thread_report report() const { return { {}, 0 }; }
  std::uint32_t id() const { return _id; }
private:
  const execution& _execution;
  std::shared_ptr<workload_simulator> _workload;
protected:
  void simulate_workload();
  const std::uint32_t _id;
  std::atomic<thread_state> _state{thread_state::starting};
  std::mt19937_64 _randomizer{};
  std::thread _thread{};
  std::chrono::duration<double, std::milli> _runtime{};
private:
  friend struct execution;
  void thread_func();
  void do_run();
  void wait_until_all_threads_are_started();
  void wait_until_initialization();
  void wait_until_benchmark_starts();
};

struct execution {
  static constexpr std::uint32_t thread_id_bits = 16;
  static constexpr std::uint32_t thread_id_mask = (1 << thread_id_bits) - 1;

  execution(std::uint32_t round, std::uint32_t runtime, std::shared_ptr<benchmark> benchmark);
  ~execution();
  void create_threads(const tao::config::value& config);
  round_report run();
  execution_state state(std::memory_order order = std::memory_order_relaxed) const;
  std::uint32_t num_threads() const { return static_cast<std::uint32_t>(_threads.size()); }
private:
  void wait_until_all_threads_are(thread_state state);

  void wait_until_running(const execution_thread& thread) const;
  void wait_until_finished(const execution_thread& thread) const;
  void wait_until_thread_state_is(const execution_thread& thread, thread_state expected) const;
  
  round_report build_report(double runtime);

  std::atomic<execution_state> _state;
  std::uint32_t _round;
  std::uint32_t _runtime;
  std::shared_ptr<benchmark> _benchmark;
  std::vector<std::unique_ptr<execution_thread>> _threads;
};