KiCad PCB EDA Suite
Loading...
Searching...
No Matches
kigit_orphan_registry.cpp
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
21
22
24
25
27{
28 // Any remaining entries represent threads we could not join during
29 // shutdown. Detach them so the OS can clean them up rather than calling
30 // std::thread's destructor on a joinable thread (which would terminate
31 // the process). The per-thread SHARED_STATE is ref-counted and outlives
32 // this registry, so the worker can still safely signal completion.
33
34 std::lock_guard<std::mutex> lock( m_mutex );
35
36 for( ENTRY& entry : m_entries )
37 {
38 if( entry.m_thread.joinable() )
39 entry.m_thread.detach();
40 }
41
42 m_entries.clear();
43}
44
45
47{
48 std::lock_guard<std::mutex> lock( m_mutex );
49 size_t count = 0;
50
51 for( const ENTRY& entry : m_entries )
52 {
53 if( !entry.m_state->m_done.load( std::memory_order_acquire ) )
54 ++count;
55 }
56
57 return count;
58}
59
60
61size_t KIGIT_ORPHAN_REGISTRY::JoinAll( std::chrono::milliseconds aTimeout )
62{
63 const auto deadline = std::chrono::steady_clock::now() + aTimeout;
64
65 // Close the registry so Register() rejects late arrivals, then move
66 // pending entries out and release m_mutex while we wait.
67
68 std::vector<ENTRY> pending;
69
70 {
71 std::lock_guard<std::mutex> lock( m_mutex );
72 m_shuttingDown = true;
73 pending = std::move( m_entries );
74 }
75
76 size_t stuck = 0;
77
78 for( ENTRY& entry : pending )
79 {
80 std::shared_ptr<SHARED_STATE> state = entry.m_state;
81
82 std::unique_lock<std::mutex> doneLock( state->m_doneMutex );
83
84 bool finished = state->m_doneCv.wait_until( doneLock, deadline,
85 [&state]()
86 {
87 return state->m_done.load(
88 std::memory_order_acquire );
89 } );
90
91 doneLock.unlock();
92
93 if( finished )
94 {
95 if( entry.m_thread.joinable() )
96 entry.m_thread.join();
97 }
98 else
99 {
100 wxLogTrace( traceGit,
101 "Orphan git thread [%s] did not finish in time; detaching",
102 entry.m_label.c_str() );
103
104 if( entry.m_thread.joinable() )
105 entry.m_thread.detach();
106
107 ++stuck;
108 }
109 }
110
111 return stuck;
112}
113
114
116{
117 for( auto it = m_entries.begin(); it != m_entries.end(); )
118 {
119 if( it->m_state->m_done.load( std::memory_order_acquire ) )
120 {
121 if( it->m_thread.joinable() )
122 it->m_thread.join();
123
124 it = m_entries.erase( it );
125 }
126 else
127 {
128 ++it;
129 }
130 }
131}
std::vector< ENTRY > m_entries
size_t JoinAll(std::chrono::milliseconds aTimeout)
Join all registered orphan threads, giving them up to aTimeout to finish cooperatively.
size_t TrackedCount() const
Return the number of tracked orphan threads that have not yet finished executing.
const wxChar *const traceGit
Flag to enable Git debugging output.