Skip to content

Commit a5e28fa

Browse files
authored
Protect access to member with mutex in CBackgroundPersister (#18)
1 parent 3cacd83 commit a5e28fa

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
@@ -14,9 +14,11 @@
1414

1515
#include <api/ImportExport.h>
1616

17+
#include <atomic>
1718
#include <functional>
1819
#include <list>
1920

21+
class CBackgroundPersisterTest;
2022

2123
namespace ml
2224
{
@@ -89,19 +91,11 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
8991
//! \return true if the function was added; false if not.
9092
bool addPersistFunc(core::CDataAdder::TPersistFunc persistFunc);
9193

92-
//! When this function is called a background persistence will be
93-
//! triggered unless there is already one in progress.
94-
bool startPersist(void);
95-
96-
//! Clear any persistence functions that have been added but not yet
97-
//! invoked. This will be rejected if a background persistence is
98-
//! currently in progress.
99-
//! \return true if the list of functions is clear; false if not.
100-
bool clear(void);
101-
10294
//! Set the first processor persist function, which is used to start the
10395
//! chain of background persistence. This will be rejected if a
10496
//! background persistence is currently in progress.
97+
//! This should be set once before startBackgroundPersistIfAppropriate is
98+
//! called.
10599
bool firstProcessorPeriodicPersistFunc(const TFirstProcessorPeriodicPersistFunc &firstProcessorPeriodicPersistFunc);
106100

107101
//! Check whether a background persist is appropriate now, and if it is
@@ -126,6 +120,17 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
126120
CBackgroundPersister &m_Owner;
127121
};
128122

123+
private:
124+
//! When this function is called a background persistence will be
125+
//! triggered unless there is already one in progress.
126+
bool startPersist(void);
127+
128+
//! Clear any persistence functions that have been added but not yet
129+
//! invoked. This will be rejected if a background persistence is
130+
//! currently in progress.
131+
//! \return true if the list of functions is clear; false if not.
132+
bool clear(void);
133+
129134
private:
130135
//! How frequently should background persistence be attempted?
131136
core_t::TTime m_PeriodicPersistInterval;
@@ -148,10 +153,10 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
148153
core::CFastMutex m_Mutex;
149154

150155
//! Is the background thread currently busy persisting data?
151-
volatile bool m_IsBusy;
156+
std::atomic_bool m_IsBusy;
152157

153158
//! Have we been told to shut down?
154-
volatile bool m_IsShutdown;
159+
std::atomic_bool m_IsShutdown;
155160

156161
using TPersistFuncList = std::list<core::CDataAdder::TPersistFunc>;
157162

@@ -164,6 +169,9 @@ class API_EXPORT CBackgroundPersister : private core::CNonCopyable
164169
// Allow the background thread to access the member variables of the owning
165170
// object
166171
friend class CBackgroundThread;
172+
173+
// For testing
174+
friend class ::CBackgroundPersisterTest;
167175
};
168176

169177

lib/api/CBackgroundPersister.cc

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

9292
core::CScopedFastLock lock(m_Mutex);
9393

94-
if (m_IsBusy)
94+
if (this->isBusy())
9595
{
9696
return false;
9797
}
@@ -113,14 +113,14 @@ bool CBackgroundPersister::addPersistFunc(core::CDataAdder::TPersistFunc persist
113113

114114
bool CBackgroundPersister::startPersist(void)
115115
{
116-
if (m_PersistFuncs.empty())
116+
core::CScopedFastLock lock(m_Mutex);
117+
118+
if (this->isBusy())
117119
{
118120
return false;
119121
}
120122

121-
core::CScopedFastLock lock(m_Mutex);
122-
123-
if (m_IsBusy)
123+
if (m_PersistFuncs.empty())
124124
{
125125
return false;
126126
}
@@ -145,7 +145,7 @@ bool CBackgroundPersister::clear(void)
145145
{
146146
core::CScopedFastLock lock(m_Mutex);
147147

148-
if (m_IsBusy)
148+
if (this->isBusy())
149149
{
150150
return false;
151151
}
@@ -159,7 +159,7 @@ bool CBackgroundPersister::firstProcessorPeriodicPersistFunc(const TFirstProcess
159159
{
160160
core::CScopedFastLock lock(m_Mutex);
161161

162-
if (m_IsBusy)
162+
if (this->isBusy())
163163
{
164164
return false;
165165
}
@@ -223,7 +223,8 @@ CBackgroundPersister::CBackgroundThread::CBackgroundThread(CBackgroundPersister
223223

224224
void CBackgroundPersister::CBackgroundThread::run(void)
225225
{
226-
226+
// The isBusy check will prevent concurrent access to
227+
// m_Owner.m_PersistFuncs here
227228
while (!m_Owner.m_PersistFuncs.empty())
228229
{
229230
if (!m_Owner.m_IsShutdown)
@@ -234,7 +235,6 @@ void CBackgroundPersister::CBackgroundThread::run(void)
234235
}
235236

236237
core::CScopedFastLock lock(m_Owner.m_Mutex);
237-
238238
m_Owner.m_IsBusy = false;
239239
}
240240

0 commit comments

Comments
 (0)