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
46size_t KIGIT_ORPHAN_REGISTRY::JoinAll( std::chrono::milliseconds aTimeout )
47{
48 const auto deadline = std::chrono::steady_clock::now() + aTimeout;
49
50 // Close the registry so Register() rejects late arrivals, then move
51 // pending entries out and release m_mutex while we wait.
52
53 std::vector<ENTRY> pending;
54
55 {
56 std::lock_guard<std::mutex> lock( m_mutex );
57 m_shuttingDown = true;
58 pending = std::move( m_entries );
59 }
60
61 size_t stuck = 0;
62
63 for( ENTRY& entry : pending )
64 {
65 std::shared_ptr<SHARED_STATE> state = entry.m_state;
66
67 std::unique_lock<std::mutex> doneLock( state->m_doneMutex );
68
69 bool finished = state->m_doneCv.wait_until( doneLock, deadline,
70 [&state]()
71 {
72 return state->m_done.load(
73 std::memory_order_acquire );
74 } );
75
76 doneLock.unlock();
77
78 if( finished )
79 {
80 if( entry.m_thread.joinable() )
81 entry.m_thread.join();
82 }
83 else
84 {
85 wxLogTrace( traceGit,
86 "Orphan git thread [%s] did not finish in time; detaching",
87 entry.m_label.c_str() );
88
89 if( entry.m_thread.joinable() )
90 entry.m_thread.detach();
91
92 ++stuck;
93 }
94 }
95
96 return stuck;
97}
98
99
101{
102 for( auto it = m_entries.begin(); it != m_entries.end(); )
103 {
104 if( it->m_state->m_done.load( std::memory_order_acquire ) )
105 {
106 if( it->m_thread.joinable() )
107 it->m_thread.join();
108
109 it = m_entries.erase( it );
110 }
111 else
112 {
113 ++it;
114 }
115 }
116}
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.
const wxChar *const traceGit
Flag to enable Git debugging output.