@@ -23,11 +23,45 @@ using namespace LOG4CXX_NS::helpers;
2323
2424IMPLEMENT_LOG4CXX_OBJECT (AppenderAttachableImpl)
2525
26+ using AppenderListPtr = std::shared_ptr<const AppenderList>;
27+
28+ /* * A vector of appender pointers. */
2629struct AppenderAttachableImpl ::priv_data
2730{
28- /* * Array of appenders. */
29- AppenderList appenderList;
31+ private: // Attributes
32+ #ifdef __cpp_lib_atomic_shared_ptr
33+ std::atomic<AppenderListPtr> pAppenderList;
34+ #else // !defined(__cpp_lib_atomic_shared_ptr)
35+ AppenderListPtr pAppenderList;
3036 mutable std::mutex m_mutex;
37+ #endif // !defined(__cpp_lib_atomic_shared_ptr)
38+
39+ public: // ...structors
40+ priv_data (const AppenderList& newList = {})
41+ : pAppenderList{ std::make_shared<const AppenderList>(newList) }
42+ {}
43+
44+ public: // Accessors
45+ AppenderListPtr getAppenders () const
46+ {
47+ #ifdef __cpp_lib_atomic_shared_ptr
48+ return pAppenderList.load (std::memory_order_acquire);
49+ #else // !defined(__cpp_lib_atomic_shared_ptr)
50+ std::lock_guard<std::mutex> lock ( m_mutex );
51+ return pAppenderList;
52+ #endif // !defined(__cpp_lib_atomic_shared_ptr)
53+ }
54+
55+ public: // Modifiers
56+ void setAppenders (const AppenderList& newList)
57+ {
58+ #ifdef __cpp_lib_atomic_shared_ptr
59+ pAppenderList.store (std::make_shared<AppenderList>(newList), std::memory_order_release);
60+ #else // !defined(__cpp_lib_atomic_shared_ptr)
61+ std::lock_guard<std::mutex> lock ( m_mutex );
62+ pAppenderList = std::make_shared<const AppenderList>(newList);
63+ #endif // !defined(__cpp_lib_atomic_shared_ptr)
64+ }
3165};
3266
3367AppenderAttachableImpl::AppenderAttachableImpl ()
@@ -36,76 +70,62 @@ AppenderAttachableImpl::AppenderAttachableImpl()
3670
3771#if LOG4CXX_ABI_VERSION <= 15
3872AppenderAttachableImpl::AppenderAttachableImpl (Pool& pool)
39- : m_priv()
4073{
4174}
4275#endif
43-
4476AppenderAttachableImpl::~AppenderAttachableImpl ()
4577{
46-
4778}
4879
80+
4981void AppenderAttachableImpl::addAppender (const AppenderPtr newAppender)
5082{
51- // Null values for newAppender parameter are strictly forbidden.
5283 if (!newAppender)
53- {
5484 return ;
55- }
56- if (!m_priv)
57- m_priv = std::make_unique<AppenderAttachableImpl::priv_data>();
58-
59- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
60- AppenderList::iterator it = std::find (
61- m_priv->appenderList .begin (), m_priv->appenderList .end (), newAppender);
62-
63- if (it == m_priv->appenderList .end ())
85+ if (m_priv)
6486 {
65- m_priv->appenderList .push_back (newAppender);
87+ auto allAppenders = m_priv->getAppenders ();
88+ if (allAppenders->end () == std::find (allAppenders->begin (), allAppenders->end (), newAppender))
89+ {
90+ auto newAppenders = *allAppenders;
91+ newAppenders.push_back (newAppender);
92+ m_priv->setAppenders (newAppenders);
93+ }
6694 }
95+ else
96+ m_priv = std::make_unique<priv_data>(AppenderList{newAppender});
6797}
6898
69- int AppenderAttachableImpl::appendLoopOnAppenders (
70- const spi::LoggingEventPtr& event,
71- Pool& p)
99+ int AppenderAttachableImpl::appendLoopOnAppenders (const spi::LoggingEventPtr& event, Pool& p)
72100{
73- int numberAppended = 0 ;
101+ int result = 0 ;
74102 if (m_priv)
75103 {
76- // FallbackErrorHandler::error() may modify our list of appenders
77- // while we are iterating over them (if it holds the same logger).
78- // So, make a local copy of the appenders that we want to iterate over
79- // before actually iterating over them.
80- AppenderList allAppenders = getAllAppenders ();
81- for (auto appender : allAppenders)
104+ auto allAppenders = m_priv->getAppenders ();
105+ for (auto & appender : *allAppenders)
82106 {
83107 appender->doAppend (event, p);
84- numberAppended++ ;
108+ ++result ;
85109 }
86110 }
87-
88- return numberAppended;
111+ return result;
89112}
90113
91114AppenderList AppenderAttachableImpl::getAllAppenders () const
92115{
93116 AppenderList result;
94117 if (m_priv)
95- {
96- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
97- result = m_priv->appenderList ;
98- }
118+ result = *m_priv->getAppenders ();
99119 return result;
100120}
101121
102122AppenderPtr AppenderAttachableImpl::getAppender (const LogString& name) const
103123{
104124 AppenderPtr result;
105- if (m_priv && !name. empty () )
125+ if (m_priv)
106126 {
107- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
108- for (auto appender : m_priv-> appenderList )
127+ auto allAppenders = m_priv->getAppenders ( );
128+ for (auto & appender : *allAppenders )
109129 {
110130 if (name == appender->getName ())
111131 {
@@ -122,8 +142,8 @@ bool AppenderAttachableImpl::isAttached(const AppenderPtr appender) const
122142 bool result = false ;
123143 if (m_priv && appender)
124144 {
125- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
126- result = std::find (m_priv-> appenderList . begin (), m_priv-> appenderList . end (), appender) != m_priv-> appenderList . end ( );
145+ auto allAppenders = m_priv->getAppenders ( );
146+ result = allAppenders-> end () != std::find (allAppenders-> begin (), allAppenders-> end (), appender);
127147 }
128148 return result;
129149}
@@ -132,38 +152,42 @@ void AppenderAttachableImpl::removeAllAppenders()
132152{
133153 if (m_priv)
134154 {
135- for ( auto a : getAllAppenders ())
136- a-> close ();
137- std::lock_guard<std::mutex> lock ( m_priv-> m_mutex );
138- m_priv->appenderList . clear ( );
155+ auto allAppenders = m_priv-> getAppenders ();
156+ for ( auto & appender : *allAppenders)
157+ appender-> close ( );
158+ m_priv->setAppenders ({} );
139159 }
140160}
141161
142162void AppenderAttachableImpl::removeAppender (const AppenderPtr appender)
143163{
144164 if (m_priv && appender)
145165 {
146- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
147- auto it = std::find (m_priv-> appenderList .begin (), m_priv-> appenderList .end (), appender);
148- if (it != m_priv-> appenderList .end ())
166+ auto newAppenders = * m_priv->getAppenders ( );
167+ auto pItem = std::find (newAppenders .begin (), newAppenders .end (), appender);
168+ if (newAppenders .end () != pItem )
149169 {
150- m_priv->appenderList .erase (it);
170+ newAppenders.erase (pItem);
171+ m_priv->setAppenders (newAppenders);
151172 }
152173 }
153174}
154175
155176void AppenderAttachableImpl::removeAppender (const LogString& name)
156177{
157- if (m_priv && !name. empty () )
178+ if (m_priv)
158179 {
159- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
160- auto it = std::find_if (m_priv-> appenderList .begin (), m_priv-> appenderList .end ()
180+ auto newAppenders = * m_priv->getAppenders ( );
181+ auto pItem = std::find_if (newAppenders .begin (), newAppenders .end ()
161182 , [&name](const AppenderPtr& appender) -> bool
162183 {
163184 return name == appender->getName ();
164185 });
165- if (it != m_priv->appenderList .end ())
166- m_priv->appenderList .erase (it);
186+ if (newAppenders.end () != pItem)
187+ {
188+ newAppenders.erase (pItem);
189+ m_priv->setAppenders (newAppenders);
190+ }
167191 }
168192}
169193
@@ -172,16 +196,17 @@ bool AppenderAttachableImpl::replaceAppender(const AppenderPtr& oldAppender, con
172196 bool found = false ;
173197 if (m_priv && oldAppender && newAppender)
174198 {
175- auto oldName = oldAppender->getName ();
176- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
177- auto it = std::find_if (m_priv-> appenderList .begin (), m_priv-> appenderList .end ()
178- , [&oldName ](const AppenderPtr& appender) -> bool
199+ auto name = oldAppender->getName ();
200+ auto newAppenders = * m_priv->getAppenders ( );
201+ auto pItem = std::find_if (newAppenders .begin (), newAppenders .end ()
202+ , [&name ](const AppenderPtr& appender) -> bool
179203 {
180- return oldName == appender->getName ();
204+ return name == appender->getName ();
181205 });
182- if (it != m_priv-> appenderList .end ())
206+ if (newAppenders .end () != pItem )
183207 {
184- *it = newAppender;
208+ *pItem = newAppender;
209+ m_priv->setAppenders (newAppenders);
185210 found = true ;
186211 }
187212 }
@@ -190,13 +215,15 @@ bool AppenderAttachableImpl::replaceAppender(const AppenderPtr& oldAppender, con
190215
191216void AppenderAttachableImpl::replaceAppenders (const AppenderList& newList)
192217{
193- auto oldAppenders = getAllAppenders ();
194- if (!m_priv)
195- m_priv = std::make_unique<AppenderAttachableImpl::priv_data>();
196- std::lock_guard<std::mutex> lock ( m_priv->m_mutex );
197- for (auto a : oldAppenders)
198- a->close ();
199- m_priv->appenderList = newList;
218+ if (m_priv)
219+ {
220+ auto allAppenders = m_priv->getAppenders ();
221+ for (auto & a : *allAppenders)
222+ a->close ();
223+ m_priv->setAppenders (newList);
224+ }
225+ else
226+ m_priv = std::make_unique<priv_data>(newList);
200227}
201228
202229
0 commit comments