KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kigit_orphan_registry.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#ifndef KIGIT_ORPHAN_REGISTRY_H_
21#define KIGIT_ORPHAN_REGISTRY_H_
22
23#include <import_export.h>
24
25#include <atomic>
26#include <chrono>
27#include <condition_variable>
28#include <memory>
29#include <mutex>
30#include <string>
31#include <thread>
32#include <utility>
33#include <vector>
34
35#include <wx/log.h>
36
37#include <trace_helpers.h>
38
56{
57public:
59
61
64
85 template <typename F>
86 bool Register( const std::string& aLabel, F&& aWork )
87 {
88 auto state = std::make_shared<SHARED_STATE>();
89
90 std::lock_guard<std::mutex> lock( m_mutex );
91
92 if( m_shuttingDown )
93 return false;
94
95 reapLocked();
96
97 // Reserve the slot before starting the thread so we don't leak a
98 // joinable std::thread if vector growth throws; emplace the entry
99 // with the state already wired up and then assign m_thread.
100
101 m_entries.emplace_back();
102 ENTRY& entry = m_entries.back();
103 entry.m_label = aLabel;
104 entry.m_state = state;
105
106 try
107 {
108 entry.m_thread = std::thread(
109 [state,
110 work = std::forward<F>( aWork ),
111 label = aLabel]() mutable
112 {
113 try
114 {
115 work();
116 }
117 catch( ... )
118 {
119 wxLogTrace( traceGit,
120 "Orphan git thread [%s] threw an exception",
121 label.c_str() );
122 }
123
124 {
125 std::lock_guard<std::mutex> doneLock( state->m_doneMutex );
126 state->m_done.store( true, std::memory_order_release );
127 }
128
129 state->m_doneCv.notify_all();
130 } );
131 }
132 catch( ... )
133 {
134 m_entries.pop_back();
135 throw;
136 }
137
138 wxLogTrace( traceGit, "Registered orphan git thread [%s]", aLabel.c_str() );
139 return true;
140 }
141
155 size_t JoinAll( std::chrono::milliseconds aTimeout );
156
157private:
159 {
160 std::atomic<bool> m_done{ false };
161 std::mutex m_doneMutex;
162 std::condition_variable m_doneCv;
163 };
164
165 struct ENTRY
166 {
167 std::thread m_thread;
168 std::string m_label;
169 std::shared_ptr<SHARED_STATE> m_state;
170 };
171
172 // Remove finished entries by joining their threads. Must be called
173 // with m_mutex held.
174 void reapLocked();
175
176 std::mutex m_mutex;
177 std::vector<ENTRY> m_entries;
178 bool m_shuttingDown = false;
179};
180
181#endif // KIGIT_ORPHAN_REGISTRY_H_
bool Register(const std::string &aLabel, F &&aWork)
Spawn a tracked orphan thread running aWork.
KIGIT_ORPHAN_REGISTRY(const KIGIT_ORPHAN_REGISTRY &)=delete
std::vector< ENTRY > m_entries
KIGIT_ORPHAN_REGISTRY & operator=(const KIGIT_ORPHAN_REGISTRY &)=delete
const wxChar *const traceGit
Flag to enable Git debugging output.
#define APIEXPORT
Macros which export functions from a DLL/DSO.
#define F(x, y, z)
Definition md5_hash.cpp:15
std::shared_ptr< SHARED_STATE > m_state
wxLogTrace helper definitions.