Coverage Report

Created: 2026-06-15 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/hierarchy.cpp
Line
Count
Source
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
#include <log4cxx/hierarchy.h>
19
#if LOG4CXX_ABI_VERSION <= 15
20
#include <log4cxx/defaultloggerfactory.h>
21
#endif
22
#include <log4cxx/helpers/loglog.h>
23
#include <log4cxx/appender.h>
24
#include <log4cxx/helpers/stringhelper.h>
25
#include <log4cxx/spi/rootlogger.h>
26
#include <algorithm>
27
#include <map>
28
#include <mutex>
29
#include <vector>
30
31
32
using namespace LOG4CXX_NS;
33
using namespace LOG4CXX_NS::spi;
34
using namespace LOG4CXX_NS::helpers;
35
36
37
typedef std::map<LogString, LoggerPtr> LoggerMap;
38
typedef std::map<LogString, ProvisionNode> ProvisionNodeMap;
39
40
struct Hierarchy::HierarchyPrivate
41
{
42
  HierarchyPrivate()
43
6
    : configured(false)
44
6
    , emittedNoAppenderWarning(false)
45
6
    , emittedNoResourceBundleWarning(false)
46
6
    , thresholdInt(Level::ALL_INT)
47
6
  {
48
6
  }
49
50
  helpers::Pool pool;
51
  mutable std::recursive_mutex mutex;
52
  mutable std::recursive_mutex configuredMutex;
53
  bool configured;
54
  bool emittedNoAppenderWarning;
55
  bool emittedNoResourceBundleWarning;
56
  int thresholdInt;
57
58
  spi::HierarchyEventListenerList listeners;
59
  LoggerPtr root;
60
  LevelPtr threshold;
61
  LoggerMap loggers;
62
  ProvisionNodeMap provisionNodes;
63
64
#if LOG4CXX_ABI_VERSION <= 15
65
  std::vector<AppenderPtr> allAppenders;
66
#endif
67
  mutable std::mutex listenerMutex;
68
69
  const char* alreadyTriedMethod{ NULL };
70
};
71
72
IMPLEMENT_LOG4CXX_OBJECT(Hierarchy)
73
74
Hierarchy::Hierarchy() :
75
6
  m_priv(std::make_unique<HierarchyPrivate>())
76
6
{
77
6
}
Unexecuted instantiation: log4cxx::Hierarchy::Hierarchy()
log4cxx::Hierarchy::Hierarchy()
Line
Count
Source
75
6
  m_priv(std::make_unique<HierarchyPrivate>())
76
6
{
77
6
}
78
79
Hierarchy::~Hierarchy()
80
6
{
81
6
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
82
6
  for (auto& item : m_priv->loggers)
83
2.83k
  {
84
2.83k
    if (auto& pLogger = item.second)
85
2.83k
    {
86
2.83k
      pLogger->removeHierarchy();
87
2.83k
      pLogger->removeAllAppenders();
88
2.83k
    }
89
2.83k
  }
90
6
  if (m_priv->root)
91
6
  {
92
6
    m_priv->root->removeHierarchy();
93
6
    m_priv->root->removeAllAppenders();
94
6
  }
95
6
}
96
97
void Hierarchy::addHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener)
98
0
{
99
0
  std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
100
101
0
  if (std::find(m_priv->listeners.begin(), m_priv->listeners.end(), listener) != m_priv->listeners.end())
102
0
  {
103
0
    LogLog::warn(LOG4CXX_STR("Ignoring attempt to add an existent listener."));
104
0
  }
105
0
  else
106
0
  {
107
0
    m_priv->listeners.push_back(listener);
108
0
  }
109
0
}
110
111
void Hierarchy::removeHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener)
112
0
{
113
0
  std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
114
115
0
    auto found = std::find(m_priv->listeners.begin(), m_priv->listeners.end(), listener);
116
0
    if(found != m_priv->listeners.end()){
117
0
        m_priv->listeners.erase(found);
118
0
    }
119
0
}
120
121
void Hierarchy::clear()
122
0
{
123
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
124
0
  m_priv->loggers.clear();
125
0
}
126
127
void Hierarchy::emitNoAppenderWarning(const Logger* logger)
128
0
{
129
0
  bool emitWarning = false;
130
0
  {
131
0
    std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
132
0
    emitWarning = !m_priv->emittedNoAppenderWarning;
133
0
    m_priv->emittedNoAppenderWarning = true;
134
0
  }
135
136
  // No appender in hierarchy, warn user only once.
137
0
  if (emitWarning)
138
0
  {
139
0
    LogLog::warn(((LogString) LOG4CXX_STR("No appender could be found for logger ("))
140
0
      + logger->getName() + LOG4CXX_STR(")."));
141
0
    LogLog::warn(LOG4CXX_STR("Please initialize the log4cxx system properly."));
142
0
  }
143
0
}
144
145
146
LoggerPtr Hierarchy::exists(const LogString& name)
147
0
{
148
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
149
150
0
  LoggerPtr logger;
151
0
  LoggerMap::iterator it = m_priv->loggers.find(name);
152
153
0
  if (it != m_priv->loggers.end())
154
0
  {
155
0
    logger = it->second;
156
0
  }
157
158
159
0
  return logger;
160
0
}
Unexecuted instantiation: log4cxx::Hierarchy::exists(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: log4cxx::Hierarchy::exists(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
161
162
void Hierarchy::setThreshold(const LevelPtr& l)
163
601
{
164
601
  if (l != 0)
165
601
  {
166
601
    std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
167
601
    setThresholdInternal(l);
168
601
  }
169
601
}
170
171
void Hierarchy::setThreshold(const LogString& levelStr)
172
0
{
173
0
  LevelPtr l(Level::toLevelLS(levelStr, 0));
174
175
0
  if (l != 0)
176
0
  {
177
0
    setThreshold(l);
178
0
  }
179
0
  else
180
0
  {
181
0
    LogLog::warn(((LogString) LOG4CXX_STR("No level could be found named \""))
182
0
      + levelStr + LOG4CXX_STR("\"."));
183
0
  }
184
0
}
Unexecuted instantiation: log4cxx::Hierarchy::setThreshold(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: log4cxx::Hierarchy::setThreshold(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
185
186
void Hierarchy::setThresholdInternal(const LevelPtr& l)
187
601
{
188
601
  m_priv->thresholdInt = l->toInt();
189
601
  m_priv->threshold = l;
190
191
601
  if (m_priv->thresholdInt != Level::ALL_INT)
192
7
  {
193
7
    m_priv->configured = true;
194
7
  }
195
601
}
196
197
void Hierarchy::fireAddAppenderEvent(const Logger* logger, const Appender* appender)
198
1.37k
{
199
1.37k
  setConfigured(true);
200
1.37k
  HierarchyEventListenerList clonedList;
201
1.37k
  {
202
1.37k
    std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
203
1.37k
    clonedList = m_priv->listeners;
204
1.37k
  }
205
206
1.37k
  for (auto& item : clonedList)
207
0
    item->addAppenderEvent(logger, appender);
208
1.37k
}
209
210
void Hierarchy::fireRemoveAppenderEvent(const Logger* logger, const Appender* appender)
211
212
1.37k
{
213
1.37k
  HierarchyEventListenerList clonedList;
214
1.37k
  {
215
1.37k
    std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
216
1.37k
    clonedList = m_priv->listeners;
217
1.37k
  }
218
1.37k
  for (auto& item : clonedList)
219
0
    item->removeAppenderEvent(logger, appender);
220
1.37k
}
221
222
LevelPtr Hierarchy::getThreshold() const
223
597
{
224
597
  return m_priv->threshold ? m_priv->threshold : Level::getAll();
225
597
}
226
227
LoggerPtr Hierarchy::getLogger(const LogString& name)
228
1.37k
{
229
1.37k
#if LOG4CXX_ABI_VERSION <= 15
230
1.37k
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<DefaultLoggerFactory>();
231
#else
232
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<LoggerFactory>();
233
#endif
234
1.37k
  return getLogger(name, defaultFactory);
235
1.37k
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
228
461
{
229
461
#if LOG4CXX_ABI_VERSION <= 15
230
461
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<DefaultLoggerFactory>();
231
#else
232
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<LoggerFactory>();
233
#endif
234
461
  return getLogger(name, defaultFactory);
235
461
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
Line
Count
Source
228
912
{
229
912
#if LOG4CXX_ABI_VERSION <= 15
230
912
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<DefaultLoggerFactory>();
231
#else
232
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<LoggerFactory>();
233
#endif
234
912
  return getLogger(name, defaultFactory);
235
912
}
236
237
LoggerPtr Hierarchy::getLogger(const LogString& name,
238
  const spi::LoggerFactoryPtr& factory)
239
15.6k
{
240
15.6k
  auto root = getRootLogger();
241
15.6k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
242
243
15.6k
  LoggerMap::iterator it = m_priv->loggers.find(name);
244
15.6k
  LoggerPtr result;
245
246
15.6k
  if (it != m_priv->loggers.end())
247
12.7k
  {
248
12.7k
    result = it->second;
249
12.7k
  }
250
15.6k
  if (!result && factory)
251
2.83k
  {
252
2.83k
#if LOG4CXX_ABI_VERSION <= 15
253
2.83k
    LoggerPtr logger(factory->makeNewLoggerInstance(m_priv->pool, name));
254
#else
255
    LoggerPtr logger(factory->makeNewLoggerInstance(name));
256
#endif
257
2.83k
    logger->setHierarchy(this);
258
2.83k
    m_priv->loggers.insert(LoggerMap::value_type(name, logger));
259
260
2.83k
    ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(name);
261
262
2.83k
    if (it2 != m_priv->provisionNodes.end())
263
397
    {
264
397
      updateChildren(it2->second, logger);
265
397
      m_priv->provisionNodes.erase(it2);
266
397
    }
267
268
2.83k
    updateParents(logger, root);
269
2.83k
    result = logger;
270
2.83k
  }
271
15.6k
  return result;
272
273
15.6k
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<log4cxx::spi::LoggerFactory> const&)
Line
Count
Source
239
14.7k
{
240
14.7k
  auto root = getRootLogger();
241
14.7k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
242
243
14.7k
  LoggerMap::iterator it = m_priv->loggers.find(name);
244
14.7k
  LoggerPtr result;
245
246
14.7k
  if (it != m_priv->loggers.end())
247
11.8k
  {
248
11.8k
    result = it->second;
249
11.8k
  }
250
14.7k
  if (!result && factory)
251
2.81k
  {
252
2.81k
#if LOG4CXX_ABI_VERSION <= 15
253
2.81k
    LoggerPtr logger(factory->makeNewLoggerInstance(m_priv->pool, name));
254
#else
255
    LoggerPtr logger(factory->makeNewLoggerInstance(name));
256
#endif
257
2.81k
    logger->setHierarchy(this);
258
2.81k
    m_priv->loggers.insert(LoggerMap::value_type(name, logger));
259
260
2.81k
    ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(name);
261
262
2.81k
    if (it2 != m_priv->provisionNodes.end())
263
397
    {
264
397
      updateChildren(it2->second, logger);
265
397
      m_priv->provisionNodes.erase(it2);
266
397
    }
267
268
2.81k
    updateParents(logger, root);
269
2.81k
    result = logger;
270
2.81k
  }
271
14.7k
  return result;
272
273
14.7k
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, std::__1::shared_ptr<log4cxx::spi::LoggerFactory> const&)
Line
Count
Source
239
926
{
240
926
  auto root = getRootLogger();
241
926
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
242
243
926
  LoggerMap::iterator it = m_priv->loggers.find(name);
244
926
  LoggerPtr result;
245
246
926
  if (it != m_priv->loggers.end())
247
911
  {
248
911
    result = it->second;
249
911
  }
250
926
  if (!result && factory)
251
15
  {
252
15
#if LOG4CXX_ABI_VERSION <= 15
253
15
    LoggerPtr logger(factory->makeNewLoggerInstance(m_priv->pool, name));
254
#else
255
    LoggerPtr logger(factory->makeNewLoggerInstance(name));
256
#endif
257
15
    logger->setHierarchy(this);
258
15
    m_priv->loggers.insert(LoggerMap::value_type(name, logger));
259
260
15
    ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(name);
261
262
15
    if (it2 != m_priv->provisionNodes.end())
263
0
    {
264
0
      updateChildren(it2->second, logger);
265
0
      m_priv->provisionNodes.erase(it2);
266
0
    }
267
268
15
    updateParents(logger, root);
269
15
    result = logger;
270
15
  }
271
926
  return result;
272
273
926
}
274
275
LoggerList Hierarchy::getCurrentLoggers() const
276
0
{
277
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
278
279
0
  LoggerList v;
280
0
  for (auto& item : m_priv->loggers)
281
0
  {
282
0
    if (auto pLogger = item.second)
283
0
      v.push_back(pLogger);
284
0
  }
285
0
  return v;
286
0
}
287
288
LoggerPtr Hierarchy::getRootLogger() const
289
33.2k
{
290
33.2k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
291
33.2k
  if (!m_priv->root)
292
6
  {
293
6
    m_priv->root = std::make_shared<RootLogger>(Level::getDebug());
294
6
    m_priv->root->setHierarchy(const_cast<Hierarchy*>(this));
295
6
  }
296
297
33.2k
  return m_priv->root;
298
33.2k
}
299
300
bool Hierarchy::isDisabled(int level) const
301
121k
{
302
121k
  return m_priv->thresholdInt > level;
303
121k
}
304
305
void Hierarchy::ensureIsConfigured(std::function<void()> configurator)
306
2.25k
{
307
2.25k
  std::lock_guard<std::recursive_mutex> lock(m_priv->configuredMutex);
308
2.25k
  if (!m_priv->configured && m_priv->alreadyTriedMethod != configurator.target_type().name())
309
1.37k
  {
310
1.37k
    configurator();
311
1.37k
    m_priv->alreadyTriedMethod = configurator.target_type().name();
312
1.37k
  }
313
2.25k
}
314
315
void Hierarchy::resetConfiguration()
316
0
{
317
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
318
319
0
  if (m_priv->root)
320
0
  {
321
0
    m_priv->root->setLevel(Level::getDebug());
322
0
    m_priv->root->setResourceBundle(0);
323
0
  }
324
0
  setThresholdInternal(Level::getAll());
325
326
0
  shutdownInternal();
327
328
0
  for (auto& item : m_priv->loggers)
329
0
  {
330
0
    if (auto pLogger = item.second)
331
0
    {
332
0
      pLogger->setLevel(0);
333
0
      pLogger->setAdditivity(true);
334
0
      pLogger->setResourceBundle(0);
335
0
    }
336
0
  }
337
0
}
338
339
void Hierarchy::shutdown()
340
1.37k
{
341
1.37k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
342
343
1.37k
  shutdownInternal();
344
1.37k
}
345
346
void Hierarchy::shutdownInternal()
347
1.37k
{
348
1.37k
  m_priv->configured = false;
349
1.37k
  m_priv->alreadyTriedMethod = NULL;
350
351
  // begin by closing nested appenders
352
1.37k
  if (m_priv->root)
353
1.37k
    m_priv->root->closeNestedAppenders();
354
355
1.37k
  for (auto& item : m_priv->loggers)
356
1.37k
  {
357
1.37k
    if (auto pLogger = item.second)
358
1.37k
      pLogger->closeNestedAppenders();
359
1.37k
  }
360
361
  // then, remove all appenders
362
1.37k
  if (m_priv->root)
363
1.37k
    m_priv->root->removeAllAppenders();
364
365
1.37k
  for (auto& item : m_priv->loggers)
366
1.37k
  {
367
1.37k
    if (auto pLogger = item.second)
368
1.37k
      pLogger->removeAllAppenders();
369
1.37k
  }
370
1.37k
}
371
372
void Hierarchy::updateParents(const LoggerPtr& logger, const LoggerPtr& root)
373
2.83k
{
374
2.83k
  const LogString name(logger->getName());
375
2.83k
  size_t length = name.size();
376
2.83k
  bool parentFound = false;
377
378
379
  // if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z"
380
2.83k
  for (size_t i = name.find_last_of(0x2E /* '.' */, length - 1);
381
119k
    (i != LogString::npos) && (i != 0);
382
117k
    i = name.find_last_of(0x2E /* '.' */, i - 1))
383
118k
  {
384
118k
    LogString substr = name.substr(0, i);
385
386
118k
    LoggerMap::iterator it = m_priv->loggers.find(substr);
387
388
118k
    if (it != m_priv->loggers.end())
389
1.05k
    {
390
1.05k
      parentFound = true;
391
1.05k
      logger->setParent( it->second );
392
1.05k
      break; // no need to update the ancestors of the closest ancestor
393
1.05k
    }
394
117k
    else
395
117k
    {
396
117k
      ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(substr);
397
398
117k
      if (it2 != m_priv->provisionNodes.end())
399
22.0k
      {
400
22.0k
        it2->second.push_back(logger);
401
22.0k
      }
402
95.0k
      else
403
95.0k
      {
404
95.0k
        ProvisionNode node(1, logger);
405
95.0k
        m_priv->provisionNodes.insert(
406
95.0k
          ProvisionNodeMap::value_type(substr, node));
407
95.0k
      }
408
117k
    }
409
118k
  }
410
411
  // If we could not find any existing parents, then link with root.
412
2.83k
  if (!parentFound)
413
1.77k
  {
414
1.77k
    logger->setParent( root );
415
1.77k
  }
416
2.83k
}
417
418
void Hierarchy::updateChildren(ProvisionNode& pn, const LoggerPtr& logger)
419
397
{
420
397
  for (auto& l : pn)
421
1.09k
  {
422
    // Unless this child already points to a correct (lower) parent,
423
    // make logger.parent point to l.parent and l.parent to logger.
424
1.09k
    if (!StringHelper::startsWith(l->getParent()->getName(), logger->getName()))
425
673
    {
426
673
      logger->setParent( l->getParent() );
427
673
      l->setParent( logger );
428
673
    }
429
1.09k
  }
430
    
431
397
}
432
433
void Hierarchy::updateChildren(const Logger* parent)
434
4.17k
{
435
4.17k
  for (auto& item : m_priv->loggers)
436
5.91M
  {
437
32.8M
    for (auto l = item.second; l; l = l->getParent())
438
26.9M
    {
439
26.9M
      if (l->getParent().get() == parent)
440
8.56k
      {
441
8.56k
        item.second->updateThreshold();
442
8.56k
        break;
443
8.56k
      }
444
26.9M
    }
445
5.91M
  }
446
4.17k
}
447
448
void Hierarchy::setConfigured(bool newValue)
449
1.37k
{
450
1.37k
  std::unique_lock<std::recursive_mutex> lock(m_priv->configuredMutex, std::try_to_lock);
451
1.37k
  if (lock.owns_lock()) // Not being auto-configured?
452
1.37k
    m_priv->configured = newValue;
453
1.37k
}
454
455
bool Hierarchy::isConfigured()
456
0
{
457
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->configuredMutex); // Blocks while auto-configuration is active
458
0
  return m_priv->configured;
459
0
}
460
461
HierarchyPtr Hierarchy::create()
462
6
{
463
6
  HierarchyPtr ret(new Hierarchy);
464
6
  return ret;
465
6
}
466
467
#if LOG4CXX_ABI_VERSION <= 15
468
void Hierarchy::clearAppenders()
469
0
{
470
0
  m_priv->allAppenders.clear();
471
0
}
472
473
void Hierarchy::addAppender(AppenderPtr appender)
474
0
{
475
0
  m_priv->allAppenders.push_back(appender);
476
0
}
477
#endif
478
479
bool Hierarchy::removeLogger(const LogString& name, bool ifNotUsed)
480
0
{
481
0
  auto parentRefCount = [this](const LoggerPtr& child) -> int
482
0
  {
483
0
    int result = 0;
484
0
    for (auto& node : m_priv->provisionNodes)
485
0
    {
486
0
      if (node.second.end() != std::find(node.second.begin(), node.second.end(), child))
487
0
        ++result;
488
0
    }
489
0
    return result;
490
0
  };
Unexecuted instantiation: hierarchy.cpp:log4cxx::Hierarchy::removeLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)::$_0::operator()(std::__1::shared_ptr<log4cxx::Logger> const&) const
Unexecuted instantiation: hierarchy.cpp:log4cxx::Hierarchy::removeLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, bool)::$_0::operator()(std::__1::shared_ptr<log4cxx::Logger> const&) const
491
0
  bool result = false;
492
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
493
0
  auto it = m_priv->loggers.find(name);
494
0
  if (it == m_priv->loggers.end())
495
0
    ;
496
0
  else if (ifNotUsed && 1 + parentRefCount(it->second) < it->second.use_count())
497
0
    ;
498
0
  else
499
0
  {
500
0
    for (auto& node : m_priv->provisionNodes)
501
0
    {
502
0
      for (size_t i = node.second.size(); 0 < i; )
503
0
      {
504
0
        if (node.second[--i] == it->second)
505
0
          node.second.erase(node.second.begin() + i);
506
0
      }
507
0
    }
508
0
    m_priv->loggers.erase(it);
509
0
    result = true;
510
0
  }
511
0
  return result;
512
0
}
Unexecuted instantiation: log4cxx::Hierarchy::removeLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)
Unexecuted instantiation: log4cxx::Hierarchy::removeLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, bool)