Skip to content

Commit

Permalink
Merge pull request #7845 from haberman/sync-stage
Browse files Browse the repository at this point in the history
Integrate from Piper for C++, Java, and Python
  • Loading branch information
haberman committed Aug 26, 2020
2 parents 1b18833 + 5c26cae commit 70b0286
Show file tree
Hide file tree
Showing 17 changed files with 312 additions and 121 deletions.
Binary file modified csharp/src/Google.Protobuf.Test/testprotos.pb
Binary file not shown.
Expand Up @@ -30,7 +30,6 @@

package com.google.protobuf;

import org.junit.Ignore;
import protobuf_unittest.NonNestedExtension;
import protobuf_unittest.NonNestedExtensionLite;
import java.lang.reflect.Method;
Expand All @@ -42,6 +41,7 @@
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.junit.Ignore;

/**
* Tests for {@link ExtensionRegistryFactory} and the {@link ExtensionRegistry} instances it
Expand All @@ -58,6 +58,7 @@
* behavior in Java 11. That seems to have broken the way the test uses a custom ClassLoader to
* exercise Lite functionality.
*/
@SuppressWarnings("JUnit4ClassUsedInJUnit3")
@Ignore
public class ExtensionRegistryFactoryTest extends TestCase {

Expand Down
3 changes: 2 additions & 1 deletion python/google/protobuf/descriptor.py
Expand Up @@ -227,7 +227,8 @@ def CopyToProto(self, proto):
proto: An empty proto instance from descriptor_pb2.
Raises:
Error: If self couldn't be serialized, due to to few constructor arguments.
Error: If self couldn't be serialized, due to to few constructor
arguments.
"""
if (self.file is not None and
self._serialized_start is not None and
Expand Down
2 changes: 1 addition & 1 deletion python/google/protobuf/internal/message_test.py
Expand Up @@ -1059,7 +1059,7 @@ def testAssignByteStringToUnicodeField(self, message_module):
self.assertIsInstance(m.optional_string, six.text_type)

def testLongValuedSlice(self, message_module):
"""It should be possible to use long-valued indices in slices
"""It should be possible to use long-valued indices in slices.
This didn't used to work in the v2 C++ implementation.
"""
Expand Down
7 changes: 2 additions & 5 deletions src/google/protobuf/compiler/cpp/cpp_helpers.cc
Expand Up @@ -1415,9 +1415,7 @@ class ParseLoopGenerator {
format_.Set("has_bits", "_has_bits_");
}

if (descriptor->file()->options().cc_enable_arenas()) {
format_("$p_ns$::Arena* arena = GetArena(); (void)arena;\n");
}
format_("$p_ns$::Arena* arena = GetArena(); (void)arena;\n");
GenerateParseLoop(descriptor, ordered_fields);
format_.Outdent();
format_("success:\n");
Expand Down Expand Up @@ -1469,8 +1467,7 @@ class ParseLoopGenerator {
// Open source doesn't support other ctypes;
ctype = field->options().ctype();
}
if (field->file()->options().cc_enable_arenas() && !field->is_repeated() &&
!options_.opensource_runtime &&
if (!field->is_repeated() && !options_.opensource_runtime &&
GetOptimizeFor(field->file(), options_) != FileOptions::LITE_RUNTIME &&
// For now only use arena string for strings with empty defaults.
field->default_value_string().empty() &&
Expand Down
3 changes: 2 additions & 1 deletion src/google/protobuf/compiler/importer_unittest.cc
Expand Up @@ -469,7 +469,8 @@ TEST_F(DiskSourceTreeTest, DiskFileToVirtualFileCanonicalization) {
&shadowing_disk_file));

#ifdef WIN32
// "C:\foo" is not mapped (it should not be misinterpreted as being under ".").
// "C:\foo" is not mapped (it should not be misinterpreted as being under
// ".").
EXPECT_EQ(DiskSourceTree::NO_MAPPING,
source_tree_.DiskFileToVirtualFile("C:\\foo", &virtual_file,
&shadowing_disk_file));
Expand Down
9 changes: 9 additions & 0 deletions src/google/protobuf/generated_message_reflection.cc
Expand Up @@ -1884,6 +1884,15 @@ bool Reflection::InsertOrLookupMapValue(Message* message,
->InsertOrLookupMapValue(key, val);
}

bool Reflection::LookupMapValue(const Message& message,
const FieldDescriptor* field, const MapKey& key,
MapValueConstRef* val) const {
USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue",
"Field is not a map field.");
val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
return GetRaw<MapFieldBase>(message, field).LookupMapValue(key, val);
}

bool Reflection::DeleteMapValue(Message* message, const FieldDescriptor* field,
const MapKey& key) const {
USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue",
Expand Down
26 changes: 26 additions & 0 deletions src/google/protobuf/map_field.cc
Expand Up @@ -44,20 +44,24 @@ MapFieldBase::~MapFieldBase() {
}

const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const {
ConstAccess();
SyncRepeatedFieldWithMap();
return *reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
}

RepeatedPtrFieldBase* MapFieldBase::MutableRepeatedField() {
MutableAccess();
SyncRepeatedFieldWithMap();
SetRepeatedDirty();
return reinterpret_cast<RepeatedPtrFieldBase*>(repeated_field_);
}

size_t MapFieldBase::SpaceUsedExcludingSelfLong() const {
ConstAccess();
mutex_.Lock();
size_t size = SpaceUsedExcludingSelfNoLock();
mutex_.Unlock();
ConstAccess();
return size;
}

Expand All @@ -70,30 +74,35 @@ size_t MapFieldBase::SpaceUsedExcludingSelfNoLock() const {
}

bool MapFieldBase::IsMapValid() const {
ConstAccess();
// "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get
// executed before state_ is checked.
int state = state_.load(std::memory_order_acquire);
return state != STATE_MODIFIED_REPEATED;
}

bool MapFieldBase::IsRepeatedFieldValid() const {
ConstAccess();
int state = state_.load(std::memory_order_acquire);
return state != STATE_MODIFIED_MAP;
}

void MapFieldBase::SetMapDirty() {
MutableAccess();
// These are called by (non-const) mutator functions. So by our API it's the
// callers responsibility to have these calls properly ordered.
state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
}

void MapFieldBase::SetRepeatedDirty() {
MutableAccess();
// These are called by (non-const) mutator functions. So by our API it's the
// callers responsibility to have these calls properly ordered.
state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
}

void MapFieldBase::SyncRepeatedFieldWithMap() const {
ConstAccess();
// acquire here matches with release below to ensure that we can only see a
// value of CLEAN after all previous changes have been synced.
switch (state_.load(std::memory_order_acquire)) {
Expand All @@ -106,6 +115,7 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const {
state_.store(CLEAN, std::memory_order_release);
}
mutex_.Unlock();
ConstAccess();
break;
case CLEAN:
mutex_.Lock();
Expand All @@ -122,6 +132,7 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const {
state_.store(CLEAN, std::memory_order_release);
}
mutex_.Unlock();
ConstAccess();
break;
default:
break;
Expand All @@ -135,6 +146,7 @@ void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
}

void MapFieldBase::SyncMapWithRepeatedField() const {
ConstAccess();
// acquire here matches with release below to ensure that we can only see a
// value of CLEAN after all previous changes have been synced.
if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_REPEATED) {
Expand All @@ -146,6 +158,7 @@ void MapFieldBase::SyncMapWithRepeatedField() const {
state_.store(CLEAN, std::memory_order_release);
}
mutex_.Unlock();
ConstAccess();
}
}

Expand Down Expand Up @@ -245,6 +258,19 @@ bool DynamicMapField::InsertOrLookupMapValue(const MapKey& map_key,
return false;
}

bool DynamicMapField::LookupMapValue(const MapKey& map_key,
MapValueConstRef* val) const {
const Map<MapKey, MapValueRef>& map = GetMap();
Map<MapKey, MapValueRef>::const_iterator iter = map.find(map_key);
if (iter == map.end()) {
return false;
}
// map_key is already in the map. Make sure (*map)[map_key] is not called.
// [] may reorder the map and iterators.
val->CopyFrom(iter->second);
return true;
}

bool DynamicMapField::DeleteMapValue(const MapKey& map_key) {
MapFieldBase::SyncMapWithRepeatedField();
Map<MapKey, MapValueRef>::iterator iter = map_.find(map_key);
Expand Down

0 comments on commit 70b0286

Please sign in to comment.