From a59d89ea8184f79c6d2c1c9f78fb1480bedd5556 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Mon, 13 Dec 2021 23:56:44 -0500 Subject: [PATCH] bytevector: add some fugly mutexes We are using ByteVectors from multiple threads in some cases. Mostly these are the status and progress threads which read the ByteVector object references embedded in BEESNOTE macros. Since it's not clear what the data race implications are, protect the shared_ptr in ByteVector with a mutex for now. Signed-off-by: Zygo Blaxell --- include/crucible/bytevector.h | 7 +++++-- lib/bytevector.cc | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/include/crucible/bytevector.h b/include/crucible/bytevector.h index e04788a..28c5028 100644 --- a/include/crucible/bytevector.h +++ b/include/crucible/bytevector.h @@ -2,6 +2,7 @@ #define _CRUCIBLE_BYTEVECTOR_H_ #include +#include #include #include @@ -21,6 +22,8 @@ namespace crucible { using iterator = value_type*; ByteVector() = default; + ByteVector(const ByteVector &that); + ByteVector& operator=(const ByteVector &that); ByteVector(size_t size); ByteVector(const ByteVector &that, size_t start, size_t length); ByteVector(iterator begin, iterator end, size_t min_size = 0); @@ -49,6 +52,8 @@ namespace crucible { private: Pointer m_ptr; size_t m_size = 0; + mutable mutex m_mutex; + friend ostream & operator<<(ostream &os, const ByteVector &bv); }; template @@ -66,8 +71,6 @@ namespace crucible { { return reinterpret_cast(data()); } - - ostream & operator<<(ostream &os, const ByteVector &bv); } #endif // _CRUCIBLE_BYTEVECTOR_H_ diff --git a/lib/bytevector.cc b/lib/bytevector.cc index 344a2cb..8895f30 100644 --- a/lib/bytevector.cc +++ b/lib/bytevector.cc @@ -4,36 +4,43 @@ #include "crucible/hexdump.h" #include "crucible/string.h" +#include + namespace crucible { using namespace std; ByteVector::iterator ByteVector::begin() const { + unique_lock lock(m_mutex); return m_ptr.get(); } ByteVector::iterator ByteVector::end() const { + unique_lock lock(m_mutex); return m_ptr.get() + m_size; } size_t ByteVector::size() const { + unique_lock lock(m_mutex); return m_size; } bool ByteVector::empty() const { + unique_lock lock(m_mutex); return !m_ptr || !m_size; } void ByteVector::clear() { + unique_lock lock(m_mutex); m_ptr.reset(); m_size = 0; } @@ -41,9 +48,28 @@ namespace crucible { ByteVector::value_type& ByteVector::operator[](size_t size) const { + unique_lock lock(m_mutex); return m_ptr.get()[size]; } + ByteVector::ByteVector(const ByteVector &that) + { + unique_lock lock(that.m_mutex); + m_ptr = that.m_ptr; + m_size = that.m_size; + } + + ByteVector& + ByteVector::operator=(const ByteVector &that) + { + unique_lock lock_this(m_mutex, defer_lock); + unique_lock lock_that(that.m_mutex, defer_lock); + lock(lock_this, lock_that); + m_ptr = that.m_ptr; + m_size = that.m_size; + return *this; + } + ByteVector::ByteVector(const ByteVector &that, size_t start, size_t length) { THROW_CHECK0(out_of_range, that.m_ptr); @@ -62,6 +88,7 @@ namespace crucible { ByteVector::value_type& ByteVector::at(size_t size) const { + unique_lock lock(m_mutex); THROW_CHECK0(out_of_range, m_ptr); THROW_CHECK2(out_of_range, size, m_size, size < m_size); return m_ptr.get()[size]; @@ -100,6 +127,9 @@ namespace crucible { bool ByteVector::operator==(const ByteVector &that) const { + unique_lock lock_this(m_mutex, defer_lock); + unique_lock lock_that(that.m_mutex, defer_lock); + lock(lock_this, lock_that); if (!m_ptr) { return !that.m_ptr; } @@ -118,6 +148,7 @@ namespace crucible { void ByteVector::erase(iterator begin, iterator end) { + unique_lock lock(m_mutex); const size_t size = end - begin; if (!size) return; THROW_CHECK0(out_of_range, m_ptr); @@ -144,11 +175,13 @@ namespace crucible { ByteVector::value_type* ByteVector::data() const { + unique_lock lock(m_mutex); return m_ptr.get(); } ostream& operator<<(ostream &os, const ByteVector &bv) { + unique_lock lock(bv.m_mutex); hexdump(os, bv); return os; }