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