thread_local_ctx.hpp (3333B)
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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | /* Relacy Race Detector * Copyright (c) 2008-2010, Dmitry S. Vyukov * All rights reserved. * This software is provided AS-IS with no warranty, either express or implied. * This software is distributed under a license and may not be copied, * modified or distributed except as expressly authorized under the * terms of the license contained in the file LICENSE.TXT in this distribution. */ #ifndef RL_THREAD_LOCAL_CTX_HPP #define RL_THREAD_LOCAL_CTX_HPP #ifdef _MSC_VER # pragma once #endif #include "base.hpp" #include "test_params.hpp" namespace rl { struct thread_local_context_iface { virtual int thread_local_alloc (void (*dtor)(intptr_t)) = 0; virtual void thread_local_free (int index) = 0; virtual void thread_local_set (int index, intptr_t value) = 0; virtual intptr_t thread_local_get (int index) = 0; virtual ~thread_local_context_iface () {} // to calm down g++ }; template<typename base_t, thread_id_t thread_count> class thread_local_contxt_impl : protected base_t { public: thread_local_contxt_impl(thread_id_t thread_count_param, test_params& params) : base_t(thread_count_param, params) { } void iteration_begin() { base_t::iteration_begin(); for (size_t ent = 0; ent != entries_.size(); ent += 1) { for (size_t th = 0; th != thread_count; th += 1) { entries_[ent].value_[th] = 0; } } } private: struct entry { bool alive_; intptr_t value_ [thread_count]; void (*dtor_) (intptr_t); }; typename vector<entry>::type entries_; using base_t::current_thread; virtual int thread_local_alloc (void (*dtor)(intptr_t)) { int index = (int)entries_.size(); entries_.resize(index + 1); entry& ent = entries_[index]; ent.alive_ = true; ent.dtor_ = dtor; for (size_t i = 0; i != thread_count; ++i) { ent.value_[i] = 0; } return index; } virtual void thread_local_free (int index) { RL_VERIFY(index >= 0 && (size_t)index < entries_.size()); entry& ent = entries_[index]; RL_VERIFY(ent.alive_); ent.alive_ = false; if (ent.dtor_) { for (size_t i = 0; i != thread_count; ++i) { if (ent.value_[i]) { ent.dtor_(ent.value_[i]); } } } } virtual void thread_local_set (int index, intptr_t value) { RL_VERIFY(index >= 0 && (size_t)index < entries_.size()); entry& ent = entries_[index]; RL_VERIFY(ent.alive_); ent.value_[current_thread()] = value; } virtual intptr_t thread_local_get (int index) { RL_VERIFY(index >= 0 && (size_t)index < entries_.size()); entry& ent = entries_[index]; RL_VERIFY(ent.alive_); return ent.value_[current_thread()]; } }; } #endif |