Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvng <viktor.govako@gmail.com>2012-07-09 01:49:35 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:40:44 +0300
commitc4c866b1dea0e1205e9da45a0eb7c7d290dcaffb (patch)
tree220f707849b0a18c5c9e0829d236656a21feecc9 /indexer
parent5f04609fff0976ad1e45902beefd8b8bef93beaa (diff)
Refactoring of maps update after downloading:
- Delay maps deleting and updating if mwm is busy; - Fix bugs with different mwm maps status; - Add better function for country bounds; - Simplify Storage logic;
Diffstat (limited to 'indexer')
-rw-r--r--indexer/index.cpp83
-rw-r--r--indexer/index.hpp9
-rw-r--r--indexer/indexer_tests/mwm_set_test.cpp28
-rw-r--r--indexer/mwm_set.cpp143
-rw-r--r--indexer/mwm_set.hpp79
5 files changed, 238 insertions, 104 deletions
diff --git a/indexer/index.cpp b/indexer/index.cpp
index 42536b6d75..69de20d718 100644
--- a/indexer/index.cpp
+++ b/indexer/index.cpp
@@ -3,6 +3,8 @@
#include "../platform/platform.hpp"
+#include "../coding/internal/file_data.hpp"
+
MwmValue::MwmValue(string const & name)
: m_cont(GetPlatform().GetReader(name)), m_name(name)
@@ -37,3 +39,84 @@ Index::~Index()
{
Cleanup();
}
+
+namespace
+{
+ void DeleteMapFiles(string const & path, bool deleteReady)
+ {
+ (void)my::DeleteFileX(path);
+ (void)my::DeleteFileX(path + RESUME_FILE_EXTENSION);
+ (void)my::DeleteFileX(path + DOWNLOADING_FILE_EXTENSION);
+
+ if (deleteReady)
+ (void)my::DeleteFileX(path + READY_FILE_EXTENSION);
+ }
+
+ string GetFullPath(string const & fileName)
+ {
+ return GetPlatform().WritablePathForFile(fileName);
+ }
+
+ void ReplaceFileWithReady(string const & fileName)
+ {
+ string const path = GetFullPath(fileName);
+ DeleteMapFiles(path, false);
+ CHECK ( my::RenameFileX(path + READY_FILE_EXTENSION, path), (path) );
+ }
+}
+
+bool Index::DeleteMap(string const & fileName)
+{
+ threads::MutexGuard mutexGuard(m_lock);
+ UNUSED_VALUE(mutexGuard);
+
+ if (!RemoveImpl(fileName))
+ return false;
+
+ DeleteMapFiles(GetFullPath(fileName), true);
+ return true;
+}
+
+bool Index::UpdateMap(string const & fileName, m2::RectD & rect)
+{
+ threads::MutexGuard mutexGuard(m_lock);
+ UNUSED_VALUE(mutexGuard);
+
+ MwmId const id = GetIdByName(fileName);
+ if (id != INVALID_MWM_ID)
+ {
+ m_info[id].m_status = MwmInfo::STATUS_UPDATE;
+ return false;
+ }
+
+ ReplaceFileWithReady(fileName);
+
+ (void)AddImpl(fileName, rect);
+ return true;
+}
+
+void Index::UpdateMwmInfo(MwmId id)
+{
+ switch (m_info[id].m_status)
+ {
+ case MwmInfo::STATUS_TO_REMOVE:
+ if (m_info[id].m_lockCount == 0)
+ {
+ DeleteMapFiles(m_name[id], true);
+
+ CHECK(RemoveImpl(id), ());
+ }
+ break;
+
+ case MwmInfo::STATUS_UPDATE:
+ if (m_info[id].m_lockCount == 0)
+ {
+ ClearCache(id);
+
+ ReplaceFileWithReady(m_name[id]);
+
+ m_info[id].m_status = MwmInfo::STATUS_ACTIVE;
+ }
+ break;
+ }
+}
diff --git a/indexer/index.hpp b/indexer/index.hpp
index 4efb59116f..90cd3f0d1e 100644
--- a/indexer/index.hpp
+++ b/indexer/index.hpp
@@ -36,6 +36,7 @@ protected:
/// @return mwm format version
virtual int GetInfo(string const & name, MwmInfo & info) const;
virtual MwmValue * CreateValue(string const & name) const;
+ virtual void UpdateMwmInfo(MwmId id);
public:
Index();
@@ -44,7 +45,8 @@ public:
class MwmLock : public MwmSet::MwmLock
{
public:
- MwmLock(Index const & index, MwmId mwmId) : MwmSet::MwmLock(index, mwmId) {}
+ MwmLock(Index const & index, MwmId mwmId)
+ : MwmSet::MwmLock(const_cast<Index &>(index), mwmId) {}
inline MwmValue * GetValue() const
{
@@ -55,6 +57,9 @@ public:
inline feature::DataHeader const & GetHeader() const { return GetValue()->GetHeader(); }
};
+ bool DeleteMap(string const & fileName);
+ bool UpdateMap(string const & fileName, m2::RectD & rect);
+
template <typename F>
void ForEachInRect(F & f, m2::RectD const & rect, uint32_t scale) const
{
@@ -147,7 +152,7 @@ private:
{
/// @todo It's better to avoid hacks with scale comparison.
- if (mwm[id].isCountry())
+ if (mwm[id].IsCountry())
{
// process countries first
ProcessMwm(f, id, cov, scale);
diff --git a/indexer/indexer_tests/mwm_set_test.cpp b/indexer/indexer_tests/mwm_set_test.cpp
index 1e0df123e4..2f839ac3ab 100644
--- a/indexer/indexer_tests/mwm_set_test.cpp
+++ b/indexer/indexer_tests/mwm_set_test.cpp
@@ -42,10 +42,10 @@ UNIT_TEST(MwmSetSmokeTest)
mwmSet.Remove("1");
mwmSet.GetMwmInfo(info);
TEST_EQUAL(info.size(), 3, ());
- TEST(info[0].isValid(), ());
+ TEST(info[0].IsActive(), ());
TEST_EQUAL(info[0].m_maxScale, 0, ());
- TEST(!info[1].isValid(), ());
- TEST(info[2].isValid(), ());
+ TEST(!info[1].IsActive(), ());
+ TEST(info[2].IsActive(), ());
TEST_EQUAL(info[2].m_maxScale, 2, ());
{
MwmSet::MwmLock lock0(mwmSet, 0);
@@ -57,11 +57,11 @@ UNIT_TEST(MwmSetSmokeTest)
mwmSet.Add("3");
mwmSet.GetMwmInfo(info);
TEST_EQUAL(info.size(), 3, ());
- TEST(info[0].isValid(), ());
+ TEST(info[0].IsActive(), ());
TEST_EQUAL(info[0].m_maxScale, 0, ());
- TEST(info[1].isValid(), ());
+ TEST(info[1].IsActive(), ());
TEST_EQUAL(info[1].m_maxScale, 3, ());
- TEST(info[2].isValid(), ());
+ TEST(info[2].IsActive(), ());
TEST_EQUAL(info[2].m_maxScale, 2, ());
{
@@ -72,23 +72,23 @@ UNIT_TEST(MwmSetSmokeTest)
}
mwmSet.GetMwmInfo(info);
TEST_EQUAL(info.size(), 4, ());
- TEST(info[0].isValid(), ());
+ TEST(info[0].IsActive(), ());
TEST_EQUAL(info[0].m_maxScale, 0, ());
- TEST(!info[1].isValid(), ());
- TEST(info[2].isValid(), ());
+ TEST(!info[1].IsActive(), ());
+ TEST(info[2].IsActive(), ());
TEST_EQUAL(info[2].m_maxScale, 2, ());
- TEST(info[3].isValid(), ());
+ TEST(info[3].IsActive(), ());
TEST_EQUAL(info[3].m_maxScale, 4, ());
mwmSet.Add("5");
mwmSet.GetMwmInfo(info);
TEST_EQUAL(info.size(), 4, ());
- TEST(info[0].isValid(), ());
+ TEST(info[0].IsActive(), ());
TEST_EQUAL(info[0].m_maxScale, 0, ());
- TEST(info[1].isValid(), ());
+ TEST(info[1].IsActive(), ());
TEST_EQUAL(info[1].m_maxScale, 5, ());
- TEST(info[2].isValid(), ());
+ TEST(info[2].IsActive(), ());
TEST_EQUAL(info[2].m_maxScale, 2, ());
- TEST(info[3].isValid(), ());
+ TEST(info[3].IsActive(), ());
TEST_EQUAL(info[3].m_maxScale, 4, ());
}
diff --git a/indexer/mwm_set.cpp b/indexer/mwm_set.cpp
index 8d763e08a8..dec88bf5df 100644
--- a/indexer/mwm_set.cpp
+++ b/indexer/mwm_set.cpp
@@ -10,34 +10,19 @@
#include "../std/memcpy.hpp"
-namespace
-{
- struct MwmIdIsEqualTo
- {
- MwmSet::MwmId m_id;
- explicit MwmIdIsEqualTo(MwmSet::MwmId id) : m_id(id) {}
- bool operator() (pair<MwmSet::MwmId, MwmSet::MwmValueBase *> const & p) const
- {
- return p.first == m_id;
- }
- };
-} // unnamed namespace
-
MwmInfo::MwmInfo() : m_lockCount(0), m_status(STATUS_REMOVED)
{
// Important: STATUS_REMOVED - is the default value.
// Apply STATUS_ACTIVE before adding to maps container.
}
-MwmSet::MwmLock::MwmLock(MwmSet const & mwmSet, MwmId mwmId)
+MwmSet::MwmLock::MwmLock(MwmSet & mwmSet, MwmId mwmId)
: m_mwmSet(mwmSet), m_id(mwmId), m_pValue(mwmSet.LockValue(mwmId))
{
- //LOG(LINFO, ("MwmLock::MwmLock()", m_id));
}
MwmSet::MwmLock::~MwmLock()
{
- //LOG(LINFO, ("MwmLock::~MwmLock()", m_id));
if (m_pValue)
m_mwmSet.UnlockValue(m_id, m_pValue);
}
@@ -46,7 +31,6 @@ MwmSet::MwmLock::~MwmLock()
MwmSet::MwmSet(size_t cacheSize)
: m_cacheSize(cacheSize)
{
- //LOG(LINFO, ("MwmSet::MwmSet()"));
}
MwmSet::~MwmSet()
@@ -60,14 +44,12 @@ void MwmSet::Cleanup()
threads::MutexGuard mutexGuard(m_lock);
UNUSED_VALUE(mutexGuard);
- //LOG(LINFO, ("MwmSet::~MwmSet()"));
-
ClearCacheImpl(m_cache.begin(), m_cache.end());
#ifdef DEBUG
- for (size_t i = 0; i < m_info.size(); ++i)
+ for (MwmId i = 0; i < m_info.size(); ++i)
{
- if (m_info[i].m_status == MwmInfo::STATUS_ACTIVE)
+ if (m_info[i].IsActive())
{
ASSERT_EQUAL(m_info[i].m_lockCount, 0, (i, m_name[i]));
ASSERT_NOT_EQUAL(m_name[i], string(), (i));
@@ -76,15 +58,15 @@ void MwmSet::Cleanup()
#endif
}
-void MwmSet::UpdateMwmInfo(MwmInfo & info)
+void MwmSet::UpdateMwmInfo(MwmId id)
{
- if (info.m_status == MwmInfo::STATUS_TO_REMOVE && info.m_lockCount == 0)
- info.m_status = MwmInfo::STATUS_REMOVED;
+ if (m_info[id].m_status == MwmInfo::STATUS_TO_REMOVE)
+ (void)RemoveImpl(id);
}
MwmSet::MwmId MwmSet::GetFreeId()
{
- MwmId const size = static_cast<MwmId>(m_info.size());
+ MwmId const size = m_info.size();
for (MwmId i = 0; i < size; ++i)
{
if (m_info[i].m_status == MwmInfo::STATUS_REMOVED)
@@ -98,11 +80,10 @@ MwmSet::MwmId MwmSet::GetFreeId()
MwmSet::MwmId MwmSet::GetIdByName(string const & name)
{
- MwmId const size = static_cast<MwmId>(m_info.size());
- for (MwmId i = 0; i < size; ++i)
+ for (MwmId i = 0; i < m_info.size(); ++i)
{
- UpdateMwmInfo(m_info[i]);
- if (m_info[i].m_status == MwmInfo::STATUS_ACTIVE && m_name[i] == name)
+ UpdateMwmInfo(i);
+ if (m_name[i] == name)
return i;
}
return INVALID_MWM_ID;
@@ -115,19 +96,27 @@ string MwmSet::MwmLock::GetCountryName() const
return src.substr(0, src.size() - strlen(DATA_FILE_EXTENSION));
}
-int MwmSet::Add(string const & fileName, m2::RectD & r)
+int MwmSet::Add(string const & fileName, m2::RectD & rect)
{
threads::MutexGuard mutexGuard(m_lock);
UNUSED_VALUE(mutexGuard);
- //LOG(LINFO, ("MwmSet::Add()", fileName));
-
- if (GetIdByName(fileName) != INVALID_MWM_ID)
+ MwmId const id = GetIdByName(fileName);
+ if (id != INVALID_MWM_ID)
{
- LOG(LWARNING, ("Trying to add already added map", fileName));
+ if (m_info[id].IsExist())
+ LOG(LWARNING, ("Trying to add already added map", fileName));
+ else
+ m_info[id].m_status = MwmInfo::STATUS_ACTIVE;
+
return -1;
}
+ return AddImpl(fileName, rect);
+}
+
+int MwmSet::AddImpl(string const & fileName, m2::RectD & rect)
+{
// this function can throw an exception for bad mwm file
MwmInfo info;
int const version = GetInfo(fileName, info);
@@ -138,18 +127,24 @@ int MwmSet::Add(string const & fileName, m2::RectD & r)
m_name[id] = fileName;
m_info[id] = info;
- r = info.m_limitRect;
- ASSERT ( r.IsValid(), () );
+ rect = info.m_limitRect;
+ ASSERT ( rect.IsValid(), () );
return version;
}
-void MwmSet::RemoveImpl(MwmId id)
+bool MwmSet::RemoveImpl(MwmId id)
{
if (m_info[id].m_lockCount == 0)
+ {
+ m_name[id].clear();
m_info[id].m_status = MwmInfo::STATUS_REMOVED;
+ return true;
+ }
else
+ {
m_info[id].m_status = MwmInfo::STATUS_TO_REMOVE;
- m_name[id].clear();
+ return false;
+ }
}
void MwmSet::Remove(string const & fileName)
@@ -157,16 +152,22 @@ void MwmSet::Remove(string const & fileName)
threads::MutexGuard mutexGuard(m_lock);
UNUSED_VALUE(mutexGuard);
- //LOG(LINFO, ("MwmSet::Remove()", fileName));
+ (void)RemoveImpl(fileName);
+}
+
+bool MwmSet::RemoveImpl(string const & fileName)
+{
+ bool ret = false;
MwmId const id = GetIdByName(fileName);
- if (id != INVALID_MWM_ID)
+ if (id != INVALID_MWM_ID && m_info[id].IsExist())
{
- RemoveImpl(id);
+ ret = RemoveImpl(id);
- // Update the cache.
- ClearCacheImpl(RemoveIfKeepValid(m_cache.begin(), m_cache.end(), MwmIdIsEqualTo(id)), m_cache.end());
+ ClearCache(id);
}
+
+ return ret;
}
void MwmSet::RemoveAllCountries()
@@ -176,43 +177,49 @@ void MwmSet::RemoveAllCountries()
for (MwmId i = 0; i < m_info.size(); ++i)
{
- if (m_info[i].isCountry())
- RemoveImpl(i);
+ if (m_info[i].IsCountry())
+ (void)RemoveImpl(i);
}
// do not call ClearCache - it's under mutex lock
ClearCacheImpl(m_cache.begin(), m_cache.end());
}
-bool MwmSet::IsLoaded(string const & fName) const
+bool MwmSet::IsLoaded(string const & file) const
{
- return (const_cast<MwmSet *>(this)->GetIdByName(fName + DATA_FILE_EXTENSION) != INVALID_MWM_ID);
+ MwmSet * p = const_cast<MwmSet *>(this);
+
+ threads::MutexGuard mutexGuard(p->m_lock);
+ UNUSED_VALUE(mutexGuard);
+
+ MwmId const id = p->GetIdByName(file + DATA_FILE_EXTENSION);
+ return (id != INVALID_MWM_ID && m_info[id].IsExist());
}
void MwmSet::GetMwmInfo(vector<MwmInfo> & info) const
{
- threads::MutexGuard mutexGuard(m_lock);
+ MwmSet * p = const_cast<MwmSet *>(this);
+
+ threads::MutexGuard mutexGuard(p->m_lock);
UNUSED_VALUE(mutexGuard);
- for (vector<MwmInfo>::iterator it = m_info.begin(); it != m_info.end(); ++it)
- UpdateMwmInfo(*it);
+ for (MwmId i = 0; i < m_info.size(); ++i)
+ p->UpdateMwmInfo(i);
info = m_info;
}
-MwmSet::MwmValueBase * MwmSet::LockValue(MwmId id) const
+MwmSet::MwmValueBase * MwmSet::LockValue(MwmId id)
{
threads::MutexGuard mutexGuard(m_lock);
UNUSED_VALUE(mutexGuard);
- //LOG(LINFO, ("MwmSet::LockContainer()", id));
-
ASSERT_LESS(id, m_info.size(), ());
if (id >= m_info.size())
return NULL;
- UpdateMwmInfo(m_info[id]);
- if (m_info[id].m_status != MwmInfo::STATUS_ACTIVE)
+ UpdateMwmInfo(id);
+ if (!m_info[id].IsActive())
return NULL;
++m_info[id].m_lockCount;
@@ -230,13 +237,11 @@ MwmSet::MwmValueBase * MwmSet::LockValue(MwmId id) const
return CreateValue(m_name[id]);
}
-void MwmSet::UnlockValue(MwmId id, MwmValueBase * p) const
+void MwmSet::UnlockValue(MwmId id, MwmValueBase * p)
{
threads::MutexGuard mutexGuard(m_lock);
UNUSED_VALUE(mutexGuard);
- //LOG(LINFO, ("MwmSet::UnlockContainer()", id));
-
ASSERT(p, (id));
ASSERT_LESS(id, m_info.size(), ());
if (id >= m_info.size() || p == 0)
@@ -245,9 +250,9 @@ void MwmSet::UnlockValue(MwmId id, MwmValueBase * p) const
ASSERT_GREATER(m_info[id].m_lockCount, 0, ());
if (m_info[id].m_lockCount > 0)
--m_info[id].m_lockCount;
- UpdateMwmInfo(m_info[id]);
+ UpdateMwmInfo(id);
- if (m_info[id].m_status == MwmInfo::STATUS_ACTIVE)
+ if (m_info[id].IsActive())
{
m_cache.push_back(make_pair(id, p));
if (m_cache.size() > m_cacheSize)
@@ -275,3 +280,21 @@ void MwmSet::ClearCacheImpl(CacheType::iterator beg, CacheType::iterator end)
delete it->second;
m_cache.erase(beg, end);
}
+
+namespace
+{
+ struct MwmIdIsEqualTo
+ {
+ MwmSet::MwmId m_id;
+ explicit MwmIdIsEqualTo(MwmSet::MwmId id) : m_id(id) {}
+ bool operator() (pair<MwmSet::MwmId, MwmSet::MwmValueBase *> const & p) const
+ {
+ return (p.first == m_id);
+ }
+ };
+}
+
+void MwmSet::ClearCache(MwmId id)
+{
+ ClearCacheImpl(RemoveIfKeepValid(m_cache.begin(), m_cache.end(), MwmIdIsEqualTo(id)), m_cache.end());
+}
diff --git a/indexer/mwm_set.hpp b/indexer/mwm_set.hpp
index 00235b7604..5bde1d3ae3 100644
--- a/indexer/mwm_set.hpp
+++ b/indexer/mwm_set.hpp
@@ -19,14 +19,21 @@ public:
uint8_t m_minScale; ///< Min zoom level of mwm.
uint8_t m_maxScale; ///< Max zoom level of mwm.
- // Does this MwmInfo represent a valid Mwm?
- inline bool isValid() const { return (m_status == STATUS_ACTIVE); }
- inline bool isCountry() const { return (m_minScale > 0); }
+ inline bool IsExist() const
+ {
+ return (m_status == STATUS_ACTIVE || m_status == STATUS_UPDATE);
+ }
+ inline bool IsCountry() const { return (m_minScale > 0); }
+ inline bool IsActive() const { return (m_status == STATUS_ACTIVE); }
-private:
- friend class MwmSet;
+ enum Status
+ {
+ STATUS_ACTIVE = 0,
+ STATUS_TO_REMOVE,
+ STATUS_REMOVED,
+ STATUS_UPDATE
+ };
- enum Status { STATUS_ACTIVE = 0, STATUS_TO_REMOVE = 1, STATUS_REMOVED = 2 };
uint8_t m_lockCount; ///< Number of locks.
uint8_t m_status; ///< Current country status.
};
@@ -49,7 +56,7 @@ public:
class MwmLock
{
public:
- MwmLock(MwmSet const & mwmSet, MwmId mwmId);
+ MwmLock(MwmSet & mwmSet, MwmId mwmId);
~MwmLock();
inline MwmValueBase * GetValue() const { return m_pValue; }
@@ -57,26 +64,33 @@ public:
inline MwmId GetID() const { return m_id; }
private:
- MwmSet const & m_mwmSet;
+ MwmSet & m_mwmSet;
MwmId m_id;
MwmValueBase * m_pValue;
};
/// Add new mwm. Returns false, if mwm with given fileName already exists.
/// @param[in] fileName File name (without full path) of country.
- /// @param[out] r Limit rect of country.
+ /// @param[out] rect Limit rect of country.
/// @return Map format version or -1 if not added
- int Add(string const & fileName, m2::RectD & r);
+ //@{
+protected:
+ int AddImpl(string const & fileName, m2::RectD & rect);
+
+public:
+ int Add(string const & fileName, m2::RectD & rect);
inline bool Add(string const & fileName)
{
m2::RectD dummy;
return (-1 != Add(fileName, dummy));
}
+ //@}
/// @name Remove mwm.
//@{
-private:
- void RemoveImpl(MwmId id);
+protected:
+ bool RemoveImpl(MwmId id);
+ bool RemoveImpl(string const & fileName);
public:
void Remove(string const & fileName);
@@ -84,9 +98,11 @@ public:
void RemoveAllCountries();
//@}
- bool IsLoaded(string const & fName) const;
+ /// @param[in] file File name without extension.
+ bool IsLoaded(string const & file) const;
- // Get ids of all mwms. Some of them may be marked to remove.
+ /// Get ids of all mwms. Some of them may be with not active status.
+ /// In that case, LockValue returns NULL.
void GetMwmInfo(vector<MwmInfo> & info) const;
// Clear caches.
@@ -100,28 +116,35 @@ protected:
void Cleanup();
private:
- static const MwmId INVALID_MWM_ID = static_cast<MwmId>(-1);
-
typedef deque<pair<MwmId, MwmValueBase *> > CacheType;
- // Update given MwmInfo.
- inline static void UpdateMwmInfo(MwmInfo & info);
-
- MwmValueBase * LockValue(MwmId id) const;
- void UnlockValue(MwmId id, MwmValueBase * p) const;
+ MwmValueBase * LockValue(MwmId id);
+ void UnlockValue(MwmId id, MwmValueBase * p);
// Find first removed mwm or add a new one.
MwmId GetFreeId();
- // Find mwm with a given name.
- MwmId GetIdByName(string const & name);
-
// Do the cleaning for [beg, end) without acquiring the mutex.
void ClearCacheImpl(CacheType::iterator beg, CacheType::iterator end);
- mutable vector<MwmInfo> m_info; // mutable needed for GetMwmInfo
- /*mutable*/ vector<string> m_name;
- mutable CacheType m_cache;
+ CacheType m_cache;
size_t m_cacheSize;
- mutable threads::Mutex m_lock;
+
+protected:
+ static const MwmId INVALID_MWM_ID = static_cast<MwmId>(-1);
+
+ /// Find mwm with a given name.
+ /// @note This function is always called under mutex m_lock.
+ MwmId GetIdByName(string const & name);
+
+ /// @note This function is always called under mutex m_lock.
+ void ClearCache(MwmId id);
+
+ /// Update given MwmInfo.
+ /// @note This function is always called under mutex m_lock.
+ virtual void UpdateMwmInfo(MwmId id);
+
+ vector<MwmInfo> m_info;
+ vector<string> m_name;
+ threads::Mutex m_lock;
};