From f157a5651c79a7a36e242af216a5d5b383ba8af2 Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Fri, 14 Nov 2014 11:50:31 -0800 Subject: Down-integrate from internal code base (C++ maps support). --- src/google/protobuf/map_field.cc | 113 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/google/protobuf/map_field.cc (limited to 'src/google/protobuf/map_field.cc') diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc new file mode 100644 index 00000000..74431628 --- /dev/null +++ b/src/google/protobuf/map_field.cc @@ -0,0 +1,113 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +namespace google { +namespace protobuf { +namespace internal { + +MapFieldBase::~MapFieldBase() { + if (repeated_field_ != NULL) delete repeated_field_; +} + +const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { + SyncRepeatedFieldWithMap(); + return *repeated_field_; +} + +RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() { + SyncRepeatedFieldWithMap(); + SetRepeatedDirty(); + return repeated_field_; +} + +int MapFieldBase::SpaceUsedExcludingSelf() const { + mutex_.Lock(); + int size = SpaceUsedExcludingSelfNoLock(); + mutex_.Unlock(); + return size; +} + +int MapFieldBase::SpaceUsedExcludingSelfNoLock() const { + if (repeated_field_ != NULL) { + return repeated_field_->SpaceUsedExcludingSelf(); + } else { + return 0; + } +} + +void MapFieldBase::InitMetadataOnce() const { + GOOGLE_CHECK(entry_descriptor_ != NULL); + GOOGLE_CHECK(assign_descriptor_callback_ != NULL); + (*assign_descriptor_callback_)(); +} + +void MapFieldBase::SetMapDirty() { state_ = STATE_MODIFIED_MAP; } + +void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; } + +void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; } + +void MapFieldBase::SyncRepeatedFieldWithMap() const { + Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_); + if (state == STATE_MODIFIED_MAP) { + mutex_.Lock(); + // Double check state, because another thread may have seen the same state + // and done the synchronization before the current thread. + if (state_ == STATE_MODIFIED_MAP) { + SyncRepeatedFieldWithMapNoLock(); + google::protobuf::internal::NoBarrier_Store(&state_, CLEAN); + } + mutex_.Unlock(); + } +} + +void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { + if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField; +} + +void MapFieldBase::SyncMapWithRepeatedField() const { + Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_); + if (state == STATE_MODIFIED_REPEATED) { + mutex_.Lock(); + // Double check state, because another thread may have seen the same state + // and done the synchronization before the current thread. + if (state_ == STATE_MODIFIED_REPEATED) { + SyncMapWithRepeatedFieldNoLock(); + google::protobuf::internal::NoBarrier_Store(&state_, CLEAN); + } + mutex_.Unlock(); + } +} + +} // namespace internal +} // namespace protobuf +} // namespace google -- cgit v1.2.3