MySQL 8.2.0
Source Code Documentation
callstack.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2022, 2023, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24
25#ifndef MYSQL_HARNESS_NET_TS_IMPL_CALLSTACK_H_
26#define MYSQL_HARNESS_NET_TS_IMPL_CALLSTACK_H_
27
28namespace net::impl {
29
30/**
31 * callstack of a thread.
32 *
33 * use-cases:
34 * - track debuginfo of call chains
35 * - check if the function calls itself
36 *
37 * Each new stackframe links to the previous stackframe and sets itself as
38 * stacktop. As callstacks are per-thread, no locking is needed.
39 *
40 * # Usage
41 *
42 * @code
43 * struct Frame {
44 * const char *filename;
45 * int line;
46 * const char *func;
47 *
48 * Frame(const char *f, int l, const char *fun):
49 * filename(f), line(l), func(fun) {}
50 * };
51 * void a() {
52 * Frame frame(__FILE__, __LINE__, __func__);
53 * Callstack<Frame>::Context stackframe(&frame);
54 * }
55 *
56 * void b() {
57 * // store a frame on the functions stack
58 * Frame frame(__FILE__, __LINE__, __func__);
59 * // link the 'frame' to the callstack
60 * Callstack<Frame>::Context stackframe(&frame);
61 *
62 * a();
63 * }
64 * @endcode
65 *
66 * @tparam Key key-type
67 * @tparam Value value-type to assign to the key
68 */
69template <class Key, class Value = unsigned char>
70class Callstack {
71 public:
72 class Context;
73 class Iterator;
74
78
79 class Context {
80 public:
81 /**
82 * construct a stackframe.
83 *
84 * sets top of stack to this frame.
85 */
86 explicit Context(const Key *k)
87 : Context(k, reinterpret_cast<Value &>(*this)) {}
88
89 Context(const Key *k, Value &v)
92 }
93
94 /**
95 * destruct a stackframe.
96 *
97 * sets top of stack to the previous stackframe.
98 */
100
101 // disable copy construct and copy-assign
102 Context(const Context &) = delete;
103 Context &operator=(const Context &) = delete;
104
105 const Key *key() const { return key_; }
106 Value *value() const { return value_; }
107
108 private:
109 friend class Callstack<Key, Value>;
110 friend class Callstack<Key, Value>::Iterator;
111
112 const Key *key_;
114
115 Context *next_; /**!< next stackframe */
116 };
117
118 /**
119 * forward-iterator over stack frames.
120 *
121 * just enough to implement for-range loops
122 */
123 class Iterator {
124 public:
125 Iterator(Context *ctx) : ctx_{ctx} {}
126
128 if (ctx_ != nullptr) ctx_ = ctx_->next_;
129 return *this;
130 }
131
132 bool operator!=(const Iterator &other) const { return ctx_ != other.ctx_; }
133
134 Context *operator*() { return ctx_; }
135
136 private:
138 };
139
140 /**
141 * check if a callstack contains a pointer already.
142 *
143 * walks the stack from the top the last element and checks if a frames key
144 * makes k
145 *
146 * @param k key to search for in the callstack
147 * @returns stored value if key is found
148 * @retval nullptr if not found.
149 */
150 static constexpr Value *contains(const Key *k) {
151 for (auto *e : Callstack<Key, Value>()) {
152 if (e->key() == k) return e->value();
153 }
154
155 return nullptr;
156 }
157
158 /** begin() iterator */
159 static Iterator begin() { return Iterator(stack_top_); }
160 /** end() iterator */
161 static Iterator end() { return Iterator(nullptr); }
162
163 private:
164 static thread_local Context *stack_top_;
165};
166
167// define thread-local initial stack-top
168template <class Key, class Value>
169thread_local
171 nullptr;
172} // namespace net::impl
173
174#endif
a nullable SQL value.
Definition: sql_value.h:39
value_type value() const
Definition: sql_value.h:45
Definition: callstack.h:79
Context(const Key *k, Value &v)
Definition: callstack.h:89
Value * value_
Definition: callstack.h:113
Context & operator=(const Context &)=delete
Value * value() const
Definition: callstack.h:106
~Context()
destruct a stackframe.
Definition: callstack.h:99
const Key * key() const
Definition: callstack.h:105
Context(const Key *k)
construct a stackframe.
Definition: callstack.h:86
const Key * key_
Definition: callstack.h:112
Context(const Context &)=delete
Context * next_
Definition: callstack.h:115
forward-iterator over stack frames.
Definition: callstack.h:123
Context * operator*()
Definition: callstack.h:134
Iterator(Context *ctx)
Definition: callstack.h:125
bool operator!=(const Iterator &other) const
Definition: callstack.h:132
Iterator & operator++()
Definition: callstack.h:127
Context * ctx_
Definition: callstack.h:137
callstack of a thread.
Definition: callstack.h:70
static Iterator begin()
begin() iterator
Definition: callstack.h:159
static constexpr Value * contains(const Key *k)
check if a callstack contains a pointer already.
Definition: callstack.h:150
static thread_local Context * stack_top_
Definition: callstack.h:164
static Iterator end()
end() iterator
Definition: callstack.h:161
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:107
Definition: buffer.h:218