MySQL 26.10.0
Source Code Documentation
ut0per_thread.h
Go to the documentation of this file.
1/* Copyright (c) 2026, Oracle and/or its affiliates.
2
3This program is free software; you can redistribute it and/or modify it under
4the terms of the GNU General Public License, version 2.0, as published by the
5Free Software Foundation.
6
7This program is designed to work with certain software (including
8but not limited to OpenSSL) that is licensed under separate terms,
9as designated in a particular file or component or in included license
10documentation. The authors of MySQL hereby grant you an additional
11permission to link the program and your derivative works with the
12separately licensed software that they have either included with
13the program or referenced in the documentation.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
18for more details.
19
20You should have received a copy of the GNU General Public License along with
21this program; if not, write to the Free Software Foundation, Inc.,
2251 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24#pragma once
25
26#include <functional>
27#include <mutex>
28#include <thread>
29#include <unordered_map>
30
31#include "univ.i"
32
33namespace ut {
34
35/** Registry of per-thread values owned by one enclosing object.
36
37This solves the case in which code needs one Value per participating thread,
38but the values must follow the lifetime of a registry.
39Plain thread_local is not enough, because thread-local objects outlive the
40registry and are destroyed only when their threads exit. */
41template <typename Value>
43 public:
44 /** Create an empty registry.
45
46 @param[in] factory callable used to create the current thread's Value on the
47 first access from that thread; must be non-empty; must not attempt calling the
48 Per_thread::operator->() as it could lead to endless recursion. */
49 explicit Per_thread(std::function<Value()> factory)
50 : m_factory(std::move(factory)) {
51 ut_a(static_cast<bool>(m_factory));
52 }
53
54 Per_thread(const Per_thread &) = delete;
55 Per_thread &operator=(const Per_thread &) = delete;
56
57 /** Return this thread's Value, creating and storing it on first access.
58
59 Repeated calls from the same thread return the same object until the
60 registry is destroyed.
61
62 As thread ids might be reused, it is possible that a new thread "inherits" the
63 Value which was used by an old thread, instead of starting with a fresh one.
64
65 @return pointer to the Value owned by this registry for the calling thread */
66 Value *operator->() {
67 const auto tid = std::this_thread::get_id();
68 {
69 std::lock_guard<std::mutex> guard(m_mutex);
70
71 auto it = m_map.find(tid);
72 if (it != m_map.end()) {
73 return &it->second;
74 }
75 }
76 /* We know no other thread can add an entry to the map for our tid, so
77 there's no need to do everything in one critical section. As m_factory()
78 might be heavy or acquire some latches, it is also better for performance
79 and deadlock-avoidance. */
80 auto instance = m_factory();
81
82 std::lock_guard<std::mutex> guard(m_mutex);
83 auto [inserted_it, inserted] = m_map.emplace(tid, std::move(instance));
84 ut_a(inserted);
85 return &inserted_it->second;
86 }
87
88 private:
89 std::function<Value()> m_factory;
90 std::mutex m_mutex;
91 std::unordered_map<std::thread::id, Value> m_map;
92};
93
94} // namespace ut
Registry of per-thread values owned by one enclosing object.
Definition: ut0per_thread.h:42
std::function< Value()> m_factory
Definition: ut0per_thread.h:89
Per_thread(const Per_thread &)=delete
Per_thread & operator=(const Per_thread &)=delete
std::mutex m_mutex
Definition: ut0per_thread.h:90
std::unordered_map< std::thread::id, Value > m_map
Definition: ut0per_thread.h:91
Per_thread(std::function< Value()> factory)
Create an empty registry.
Definition: ut0per_thread.h:49
Value * operator->()
Return this thread's Value, creating and storing it on first access.
Definition: ut0per_thread.h:66
Define std::hash<Gtid>.
Definition: gtid.h:355
pid_type get_id()
Definition: process.h:48
This file contains a set of libraries providing overloads for regular dynamic allocation routines whi...
Definition: aligned_alloc.h:48
Version control for database, common definitions, and include files.
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:97