2020#include " Poco/NumberParser.h"
2121#include " Poco/String.h"
2222
23+ #include < cassert>
2324#include < mutex>
2425
2526namespace
@@ -37,12 +38,20 @@ std::mutex & getLoggerMutex()
3738 return *logger_mutex;
3839}
3940
41+ struct LoggerEntry
42+ {
43+ Poco::Logger * logger;
44+ bool owned_by_shared_ptr = false ;
45+ };
46+
47+ using LoggerMap = std::unordered_map<std::string, LoggerEntry>;
48+ LoggerMap * _pLoggerMap = nullptr ;
49+
4050}
4151
4252namespace Poco {
4353
4454
45- Logger::LoggerMap* Logger::_pLoggerMap = 0 ;
4655const std::string Logger::ROOT;
4756
4857
@@ -134,12 +143,12 @@ void Logger::setLevel(const std::string& name, int level)
134143 if (_pLoggerMap)
135144 {
136145 std::string::size_type len = name.length ();
137- for (LoggerMap::iterator it = _pLoggerMap-> begin (); it != _pLoggerMap-> end (); ++it )
146+ for (auto & it : * _pLoggerMap)
138147 {
139148 if (len == 0 ||
140- (it-> first .compare (0 , len, name) == 0 && (it-> first .length () == len || it-> first [len] == ' .' )))
149+ (it. first .compare (0 , len, name) == 0 && (it. first .length () == len || it. first [len] == ' .' )))
141150 {
142- it-> second ->setLevel (level);
151+ it. second . logger ->setLevel (level);
143152 }
144153 }
145154 }
@@ -153,12 +162,12 @@ void Logger::setChannel(const std::string& name, Channel* pChannel)
153162 if (_pLoggerMap)
154163 {
155164 std::string::size_type len = name.length ();
156- for (LoggerMap::iterator it = _pLoggerMap-> begin (); it != _pLoggerMap-> end (); ++it )
165+ for (auto & it : * _pLoggerMap)
157166 {
158167 if (len == 0 ||
159- (it-> first .compare (0 , len, name) == 0 && (it-> first .length () == len || it-> first [len] == ' .' )))
168+ (it. first .compare (0 , len, name) == 0 && (it. first .length () == len || it. first [len] == ' .' )))
160169 {
161- it-> second ->setChannel (pChannel);
170+ it. second . logger ->setChannel (pChannel);
162171 }
163172 }
164173 }
@@ -172,12 +181,12 @@ void Logger::setProperty(const std::string& loggerName, const std::string& prope
172181 if (_pLoggerMap)
173182 {
174183 std::string::size_type len = loggerName.length ();
175- for (LoggerMap::iterator it = _pLoggerMap-> begin (); it != _pLoggerMap-> end (); ++it )
184+ for (auto & it : * _pLoggerMap)
176185 {
177186 if (len == 0 ||
178- (it-> first .compare (0 , len, loggerName) == 0 && (it-> first .length () == len || it-> first [len] == ' .' )))
187+ (it. first .compare (0 , len, loggerName) == 0 && (it. first .length () == len || it. first [len] == ' .' )))
179188 {
180- it-> second ->setProperty (propertyName, value);
189+ it. second . logger ->setProperty (propertyName, value);
181190 }
182191 }
183192 }
@@ -304,35 +313,84 @@ struct LoggerDeleter
304313{
305314 void operator ()(Poco::Logger * logger)
306315 {
307- if (Logger::destroy (logger->name ()))
316+ std::lock_guard<std::mutex> lock (getLoggerMutex ());
317+
318+ // / If logger infrastructure is destroyed just decrement logger reference count
319+ if (!_pLoggerMap)
320+ {
321+ logger->release ();
308322 return ;
323+ }
324+
325+ auto it = _pLoggerMap->find (logger->name ());
326+ assert (it != _pLoggerMap->end ());
309327
310- logger->release ();
328+ /* * If reference count is 1, this means this shared pointer owns logger
329+ * and need destroy it.
330+ */
331+ size_t reference_count_before_release = logger->release ();
332+ if (reference_count_before_release == 1 )
333+ {
334+ assert (it->second .owned_by_shared_ptr );
335+ _pLoggerMap->erase (it);
336+ }
311337 }
312338};
313339
340+
314341inline LoggerPtr makeLoggerPtr (Logger & logger)
315342{
316- logger.duplicate ();
317343 return std::shared_ptr<Logger>(&logger, LoggerDeleter ());
318344}
319345
320346}
321347
348+
322349Logger& Logger::get (const std::string& name)
323350{
324351 std::lock_guard<std::mutex> lock (getLoggerMutex ());
325352
326- return unsafeGet (name);
353+ Logger & logger = unsafeGet (name);
354+
355+ /* * If there are already shared pointer created for this logger
356+ * we need to increment Logger reference count and now logger
357+ * is owned by logger infrastructure.
358+ */
359+ auto it = _pLoggerMap->find (name);
360+ if (it->second .owned_by_shared_ptr )
361+ {
362+ it->second .logger ->duplicate ();
363+ it->second .owned_by_shared_ptr = false ;
364+ }
365+
366+ return logger;
327367}
328368
369+
329370LoggerPtr Logger::getShared (const std::string & name)
330371{
331372 std::lock_guard<std::mutex> lock (getLoggerMutex ());
373+ bool logger_exists = _pLoggerMap && _pLoggerMap->contains (name);
332374
333- return makeLoggerPtr (unsafeGet (name));
375+ Logger & logger = unsafeGet (name);
376+
377+ /* * If logger already exists, then this shared pointer does not own it.
378+ * If logger does not exists, logger infrastructure could be already destroyed
379+ * or logger was created.
380+ */
381+ if (logger_exists)
382+ {
383+ logger.duplicate ();
384+ }
385+ else if (_pLoggerMap)
386+ {
387+ _pLoggerMap->find (name)->second .owned_by_shared_ptr = true ;
388+ }
389+
390+ return makeLoggerPtr (logger);
334391}
335392
393+
336394Logger& Logger::unsafeGet (const std::string& name)
337395{
338396 Logger* pLogger = find (name);
@@ -364,7 +422,10 @@ LoggerPtr Logger::createShared(const std::string & name, Channel * pChannel, int
364422{
365423 std::lock_guard<std::mutex> lock (getLoggerMutex ());
366424
367- return makeLoggerPtr (unsafeCreate (name, pChannel, level));
425+ Logger & logger = unsafeCreate (name, pChannel, level);
426+ _pLoggerMap->find (name)->second .owned_by_shared_ptr = true ;
427+
428+ return makeLoggerPtr (logger);
368429}
369430
370431Logger& Logger::root ()
@@ -389,10 +450,14 @@ void Logger::shutdown()
389450
390451 if (_pLoggerMap)
391452 {
392- for (LoggerMap::iterator it = _pLoggerMap-> begin (); it != _pLoggerMap-> end (); ++it )
453+ for (auto & it : * _pLoggerMap)
393454 {
394- it->second ->release ();
455+ if (it.second .owned_by_shared_ptr )
456+ continue ;
457+
458+ it.second .logger ->release ();
395459 }
460+
396461 delete _pLoggerMap;
397462 _pLoggerMap = 0 ;
398463 }
@@ -405,32 +470,12 @@ Logger* Logger::find(const std::string& name)
405470 {
406471 LoggerMap::iterator it = _pLoggerMap->find (name);
407472 if (it != _pLoggerMap->end ())
408- return it->second ;
473+ return it->second . logger ;
409474 }
410475 return 0 ;
411476}
412477
413478
414- bool Logger::destroy (const std::string& name)
415- {
416- std::lock_guard<std::mutex> lock (getLoggerMutex ());
417-
418- if (_pLoggerMap)
419- {
420- LoggerMap::iterator it = _pLoggerMap->find (name);
421- if (it != _pLoggerMap->end ())
422- {
423- if (it->second ->release () == 1 )
424- _pLoggerMap->erase (it);
425-
426- return true ;
427- }
428- }
429-
430- return false ;
431- }
432-
433-
434479void Logger::names (std::vector<std::string>& names)
435480{
436481 std::lock_guard<std::mutex> lock (getLoggerMutex ());
@@ -538,7 +583,8 @@ void Logger::add(Logger* pLogger)
538583{
539584 if (!_pLoggerMap)
540585 _pLoggerMap = new LoggerMap;
541- _pLoggerMap->insert (LoggerMap::value_type (pLogger->name (), pLogger));
586+
587+ _pLoggerMap->emplace (pLogger->name (), LoggerEntry{pLogger, false /* owned_by_shared_ptr*/ });
542588}
543589
544590
0 commit comments