diff --git a/CMakeLists.txt b/CMakeLists.txt index 09990ef4..f019d935 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ INCLUDE(messmer/cmake/tools) # Actually create targets: EXEcutables and libraries. ADD_BII_TARGETS() +ADD_BOOST(thread) + ACTIVATE_CPP14() # You can safely delete lines from here... diff --git a/implementations/onblocks/datatreestore/DataTree.cpp b/implementations/onblocks/datatreestore/DataTree.cpp index 11f7de0a..b745e764 100644 --- a/implementations/onblocks/datatreestore/DataTree.cpp +++ b/implementations/onblocks/datatreestore/DataTree.cpp @@ -21,6 +21,9 @@ using blobstore::onblocks::datanodestore::DataNodeLayout; using std::unique_ptr; using std::dynamic_pointer_cast; using std::function; +using boost::shared_mutex; +using boost::shared_lock; +using boost::unique_lock; using cpputils::dynamic_pointer_move; using cpputils::optional_ownership_ptr; @@ -32,7 +35,7 @@ namespace onblocks { namespace datatreestore { DataTree::DataTree(DataNodeStore *nodeStore, unique_ptr rootNode) - : _nodeStore(nodeStore), _rootNode(std::move(rootNode)) { + : _mutex(), _nodeStore(nodeStore), _rootNode(std::move(rootNode)) { } DataTree::~DataTree() { @@ -109,6 +112,7 @@ unique_ptr DataTree::releaseRootNode() { } void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function func) { + shared_lock lock(_mutex); const_cast(this)->traverseLeaves(beginIndex, endIndex, [func](const DataLeafNode* leaf, uint32_t leafIndex) { func(const_cast(leaf), leafIndex); }); @@ -116,6 +120,7 @@ void DataTree::traverseLeaves(uint32_t beginIndex, uint32_t endIndex, function func) const { + shared_lock lock(_mutex); assert(beginIndex <= endIndex); //TODO assert(beginIndex <= numLeaves()); //TODO assert(endIndex <= numLeaves()); @@ -155,6 +160,7 @@ uint64_t DataTree::numStoredBytes() const { } uint64_t DataTree::numStoredBytes(const DataNode &root) const { + shared_lock lock(_mutex); const DataLeafNode *leaf = dynamic_cast(&root); if (leaf != nullptr) { return leaf->numBytes(); @@ -169,6 +175,7 @@ uint64_t DataTree::numStoredBytes(const DataNode &root) const { } void DataTree::resizeNumBytes(uint64_t newNumBytes) { + unique_lock lock(_mutex); //TODO Faster implementation possible (no addDataLeaf()/removeLastDataLeaf() in a loop, but directly resizing) LastLeaf(_rootNode.get())->resize(_nodeStore->layout().maxBytesPerLeaf()); uint64_t currentNumBytes = numStoredBytes(); diff --git a/implementations/onblocks/datatreestore/DataTree.h b/implementations/onblocks/datatreestore/DataTree.h index 498ba1cc..637be286 100644 --- a/implementations/onblocks/datatreestore/DataTree.h +++ b/implementations/onblocks/datatreestore/DataTree.h @@ -6,6 +6,8 @@ #include #include #include "../datanodestore/DataNodeView.h" +//TODO Replace with C++14 once std::shared_mutex is supported +#include namespace blockstore { class Key; @@ -36,6 +38,7 @@ public: uint64_t numStoredBytes() const; private: + mutable boost::shared_mutex _mutex; datanodestore::DataNodeStore *_nodeStore; std::unique_ptr _rootNode;