Skip to content

Commit 9cc58e6

Browse files
authored
Protect access to member with mutex in CBackgroundPersister (#18)
1 parent 7603890 commit 9cc58e6

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed

include/api/CBackgroundPersister.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@
2323

2424
#include <api/ImportExport.h>
2525

26+
#include <atomic>
2627
#include <functional>
2728
#include <list>
2829

30+
class CBackgroundPersisterTest;
2931

3032
namespace ml
3133
{
@@ -98,19 +100,11 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
98100
//! \return true if the function was added; false if not.
99101
bool addPersistFunc(core::CDataAdder::TPersistFunc persistFunc);
100102

101-
//! When this function is called a background persistence will be
102-
//! triggered unless there is already one in progress.
103-
bool startPersist(void);
104-
105-
//! Clear any persistence functions that have been added but not yet
106-
//! invoked. This will be rejected if a background persistence is
107-
//! currently in progress.
108-
//! \return true if the list of functions is clear; false if not.
109-
bool clear(void);
110-
111103
//! Set the first processor persist function, which is used to start the
112104
//! chain of background persistence. This will be rejected if a
113105
//! background persistence is currently in progress.
106+
//! This should be set once before startBackgroundPersistIfAppropriate is
107+
//! called.
114108
bool firstProcessorPeriodicPersistFunc(const TFirstProcessorPeriodicPersistFunc &firstProcessorPeriodicPersistFunc);
115109

116110
//! Check whether a background persist is appropriate now, and if it is
@@ -135,6 +129,17 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
135129
CBackgroundPersister &m_Owner;
136130
};
137131

132+
private:
133+
//! When this function is called a background persistence will be
134+
//! triggered unless there is already one in progress.
135+
bool startPersist(void);
136+
137+
//! Clear any persistence functions that have been added but not yet
138+
//! invoked. This will be rejected if a background persistence is
139+
//! currently in progress.
140+
//! \return true if the list of functions is clear; false if not.
141+
bool clear(void);
142+
138143
private:
139144
//! How frequently should background persistence be attempted?
140145
core_t::TTime m_PeriodicPersistInterval;
@@ -157,10 +162,10 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
157162
core::CFastMutex m_Mutex;
158163

159164
//! Is the background thread currently busy persisting data?
160-
volatile bool m_IsBusy;
165+
std::atomic_bool m_IsBusy;
161166

162167
//! Have we been told to shut down?
163-
volatile bool m_IsShutdown;
168+
std::atomic_bool m_IsShutdown;
164169

165170
using TPersistFuncList = std::list<core::CDataAdder::TPersistFunc>;
166171

@@ -173,6 +178,9 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
173178
// Allow the background thread to access the member variables of the owning
174179
// object
175180
friend class CBackgroundThread;
181+
182+
// For testing
183+
friend class ::CBackgroundPersisterTest;
176184
};
177185

178186

lib/api/CBackgroundPersister.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ bool CBackgroundPersister::addPersistFunc(core::CDataAdder::TPersistFunc persist
100100

101101
core::CScopedFastLock lock(m_Mutex);
102102

103-
if (m_IsBusy)
103+
if (this->isBusy())
104104
{
105105
return false;
106106
}
@@ -122,14 +122,14 @@ bool CBackgroundPersister::addPersistFunc(core::CDataAdder::TPersistFunc persist
122122

123123
bool CBackgroundPersister::startPersist(void)
124124
{
125-
if (m_PersistFuncs.empty())
125+
core::CScopedFastLock lock(m_Mutex);
126+
127+
if (this->isBusy())
126128
{
127129
return false;
128130
}
129131

130-
core::CScopedFastLock lock(m_Mutex);
131-
132-
if (m_IsBusy)
132+
if (m_PersistFuncs.empty())
133133
{
134134
return false;
135135
}
@@ -154,7 +154,7 @@ bool CBackgroundPersister::clear(void)
154154
{
155155
core::CScopedFastLock lock(m_Mutex);
156156

157-
if (m_IsBusy)
157+
if (this->isBusy())
158158
{
159159
return false;
160160
}
@@ -168,7 +168,7 @@ bool CBackgroundPersister::firstProcessorPeriodicPersistFunc(const TFirstProcess
168168
{
169169
core::CScopedFastLock lock(m_Mutex);
170170

171-
if (m_IsBusy)
171+
if (this->isBusy())
172172
{
173173
return false;
174174
}
@@ -232,7 +232,8 @@ CBackgroundPersister::CBackgroundThread::CBackgroundThread(CBackgroundPersister
232232

233233
void CBackgroundPersister::CBackgroundThread::run(void)
234234
{
235-
235+
// The isBusy check will prevent concurrent access to
236+
// m_Owner.m_PersistFuncs here
236237
while (!m_Owner.m_PersistFuncs.empty())
237238
{
238239
if (!m_Owner.m_IsShutdown)
@@ -243,7 +244,6 @@ void CBackgroundPersister::CBackgroundThread::run(void)
243244
}
244245

245246
core::CScopedFastLock lock(m_Owner.m_Mutex);
246-
247247
m_Owner.m_IsBusy = false;
248248
}
249249

0 commit comments

Comments
 (0)