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; }