Browse Source

am ec0b12c3: Merge "Don\'t reset cachedSize to 0 in getSerializedSize"

* commit 'ec0b12c34a6329d2f98003e9102fe2d75726c797':
  Don't reset cachedSize to 0 in getSerializedSize
Wink Saville 11 năm trước cách đây
mục cha
commit
9d89464330

+ 9 - 0
java/README.txt

@@ -437,6 +437,15 @@ and the runtime overhead. An overview of Nano features:
   MessageNano.
 - The 'bytes' type translates to the Java type byte[].
 
+The generated messages are not thread-safe for writes, but may be
+used simultaneously from multiple threads in a read-only manner.
+In other words, an appropriate synchronization mechanism (such as
+a ReadWriteLock) must be used to ensure that a message, its
+ancestors, and descendants are not accessed by any other threads
+while the message is being modified. Field reads, getter methods,
+toByteArray(...), writeTo(...), getCachedSize(), and
+getSerializedSize() are all considered read-only operations.
+
 IMPORTANT: If you have fields with defaults and opt out of accessors
 
 How fields with defaults are serialized has changed. Because we don't

+ 1 - 2
java/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java

@@ -47,7 +47,7 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
     protected List<UnknownFieldData> unknownFieldData;
 
     @Override
-    public int getSerializedSize() {
+    protected int computeSerializedSize() {
         int size = 0;
         int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size();
         for (int i = 0; i < unknownFieldCount; i++) {
@@ -55,7 +55,6 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
             size += CodedOutputByteBufferNano.computeRawVarint32Size(unknownField.tag);
             size += unknownField.bytes.length;
         }
-        cachedSize = size;
         return size;
     }
 

+ 14 - 5
java/src/main/java/com/google/protobuf/nano/MessageNano.java

@@ -38,7 +38,7 @@ import java.io.IOException;
  * @author wink@google.com Wink Saville
  */
 public abstract class MessageNano {
-    protected int cachedSize = -1;
+    protected volatile int cachedSize = -1;
 
     /**
      * Get the number of bytes required to encode this message.
@@ -60,10 +60,19 @@ public abstract class MessageNano {
      * The size is cached and the cached result can be retrieved
      * using getCachedSize().
      */
-    public int getSerializedSize() {
-        // This is overridden if the generated message has serialized fields.
-        cachedSize = 0;
-        return 0;
+    public final int getSerializedSize() {
+        int size = computeSerializedSize();
+        cachedSize = size;
+        return size;
+    }
+
+    /**
+     * Computes the number of bytes required to encode this message. This does not update the
+     * cached size.
+     */
+    protected int computeSerializedSize() {
+      // This is overridden if the generated message has serialized fields.
+      return 0;
     }
 
     /**

+ 15 - 0
java/src/test/java/com/google/protobuf/NanoTest.java

@@ -105,6 +105,14 @@ public class NanoTest extends TestCase {
     assertEquals(456, newMsg.d);
     assertEquals(2, msg.nestedMsg.bb);
     assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
+
+    msg.nestedMsg = null;
+    assertEquals(msgSerializedSize, msg.getCachedSize());
+    assertTrue(msgSerializedSize != msg.getSerializedSize());
+
+    msg.clear();
+    assertEquals(0, msg.getCachedSize());
+    assertEquals(0, msg.getSerializedSize());
   }
 
   public void testRecursiveMessageNano() throws Exception {
@@ -3532,6 +3540,13 @@ public class NanoTest extends TestCase {
     assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools));
   }
 
+  public void testMessageNoFields() {
+    SingleMessageNano msg = new SingleMessageNano();
+    assertEquals(0, msg.getSerializedSize());
+    assertEquals(0, msg.getCachedSize());
+    assertEquals(0, MessageNano.toByteArray(msg).length);
+  }
+
   private void assertRepeatedPackablesEqual(
       NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
     // Not using MessageNano.equals() -- that belongs to a separate test.

+ 2 - 3
src/google/protobuf/compiler/javanano/javanano_message.cc

@@ -304,8 +304,8 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
   printer->Print(
     "\n"
     "@Override\n"
-    "public int getSerializedSize() {\n"
-    "  int size = super.getSerializedSize();\n");
+    "protected int computeSerializedSize() {\n"
+    "  int size = super.computeSerializedSize();\n");
   printer->Indent();
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -314,7 +314,6 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
 
   printer->Outdent();
   printer->Print(
-    "  cachedSize = size;\n"
     "  return size;\n"
     "}\n");
 }