ChaiScript / ChaiScript
1
// This file is distributed under the BSD License.
2
// See "license.txt" for details.
3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5
// http://www.chaiscript.com
6

7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9

10

11
#ifndef CHAISCRIPT_THREADING_HPP_
12
#define CHAISCRIPT_THREADING_HPP_
13

14

15
#include <unordered_map>
16

17
#ifndef CHAISCRIPT_NO_THREADS
18
#include <thread>
19
#include <mutex>
20
#include <shared_mutex>
21
#else
22
#ifndef CHAISCRIPT_NO_THREADS_WARNING
23
#pragma message ("ChaiScript is compiling without thread safety.")
24
#endif
25
#endif
26

27
#include "chaiscript_defines.hpp"
28

29
/// \file
30
///
31
/// This file contains code necessary for thread support in ChaiScript.
32
/// If the compiler definition CHAISCRIPT_NO_THREADS is defined then thread safety
33
/// is disabled in ChaiScript. This has the result that some code is faster, because mutex locks are not required.
34
/// It also has the side effect that the chaiscript::ChaiScript object may not be accessed from more than
35
/// one thread simultaneously.
36

37
namespace chaiscript
38
{
39
  namespace detail
40
  {
41
    /// If threading is enabled, then this namespace contains std thread classes.
42
    /// If threading is not enabled, then stubbed in wrappers that do nothing are provided.
43
    /// This allows us to avoid \#ifdef code in the sections that need thread safety.
44
    namespace threading
45
    {
46

47
#ifndef CHAISCRIPT_NO_THREADS
48

49
      template<typename T>
50
        using unique_lock = std::unique_lock<T>;
51

52
      template<typename T>
53
        using shared_lock = std::shared_lock<T>;
54

55
      template<typename T>
56
        using lock_guard = std::lock_guard<T>;
57

58

59
      using std::shared_mutex;
60

61
      using std::mutex;
62

63
      using std::recursive_mutex;
64

65
      /// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If
66
      /// threading is not enabled, the class always returns the same data, regardless of which thread it is called from.
67
      template<typename T>
68
        class Thread_Storage
69
        {
70
          public:
71
            Thread_Storage() = default;
72
            Thread_Storage(const Thread_Storage &) = delete;
73
            Thread_Storage(Thread_Storage &&) = delete;
74
            Thread_Storage &operator=(const Thread_Storage &) = delete;
75
            Thread_Storage &operator=(Thread_Storage &&) = delete;
76

77 1
            ~Thread_Storage()
78
            {
79 1
              t().erase(this);
80
            }
81

82 1
            inline const T *operator->() const noexcept
83
            {
84 1
              return &(t()[this]);
85
            }
86

87 1
            inline const T &operator*() const noexcept
88
            {
89 1
              return t()[this];
90
            }
91

92 1
            inline T *operator->() noexcept
93
            {
94 1
              return &(t()[this]);
95
            }
96

97 1
            inline T &operator*() noexcept
98
            {
99 1
              return t()[this];
100
            }
101

102

103
            void *m_key;
104

105
          private:
106
            /// todo: is it valid to make this noexcept? The allocation could fail, but if it
107
            /// does there is no possible way to recover
108 1
            static std::unordered_map<const void*, T> &t() noexcept
109
            {
110 1
              static thread_local std::unordered_map<const void *, T> my_t;
111 1
              return my_t;
112
            }
113
        };
114

115
#else // threading disabled
116
      template<typename T>
117
      class unique_lock 
118
      {
119
        public:
120 1
          constexpr explicit unique_lock(T &) noexcept {}
121 0
          constexpr void lock() noexcept {}
122 0
          constexpr void unlock() noexcept {}
123
      };
124

125
      template<typename T>
126
      class shared_lock 
127
      {
128
        public:
129 1
          constexpr explicit shared_lock(T &) noexcept {}
130
          constexpr void lock() noexcept {}
131
          constexpr void unlock() noexcept {}
132
      };
133

134
      template<typename T>
135
      class lock_guard 
136
      {
137
        public:
138 0
          constexpr explicit lock_guard(T &) noexcept {}
139
      };
140

141
      class shared_mutex { };
142

143
      class recursive_mutex {};
144

145

146
      template<typename T>
147
        class Thread_Storage
148
        {
149
          public:
150 1
            constexpr explicit Thread_Storage() noexcept
151
            {
152
            }
153

154
            constexpr inline T *operator->() const noexcept
155
            {
156
              return &obj;
157
            }
158

159
            constexpr inline T &operator*() const noexcept
160
            {
161
              return obj;
162
            }
163

164
          private:
165
            mutable T obj;
166
        };
167

168
#endif
169
    }
170
  }
171
}
172

173

174

175
#endif
176

Read our documentation on viewing source code .

Loading