Ver Fonte

Merge "Don't reset cachedSize to 0 in getSerializedSize"

Max Cai há 11 anos atrás
pai
commit
56cba8eeae

+ 9 - 0
java/README.txt

@@ -437,6 +437,15 @@ and the runtime overhead. An overview of Nano features:
   MessageNano.
   MessageNano.
 - The 'bytes' type translates to the Java type byte[].
 - 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
 IMPORTANT: If you have fields with defaults and opt out of accessors
 
 
 How fields with defaults are serialized has changed. Because we don't
 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;
     protected List<UnknownFieldData> unknownFieldData;
 
 
     @Override
     @Override
-    public int getSerializedSize() {
+    protected int computeSerializedSize() {
         int size = 0;
         int size = 0;
         int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size();
         int unknownFieldCount = unknownFieldData == null ? 0 : unknownFieldData.size();
         for (int i = 0; i < unknownFieldCount; i++) {
         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 += CodedOutputByteBufferNano.computeRawVarint32Size(unknownField.tag);
             size += unknownField.bytes.length;
             size += unknownField.bytes.length;
         }
         }
-        cachedSize = size;
         return size;
         return size;
     }
     }
 
 

+ 13 - 4
java/src/main/java/com/google/protobuf/nano/MessageNano.java

@@ -38,7 +38,7 @@ import java.io.IOException;
  * @author wink@google.com Wink Saville
  * @author wink@google.com Wink Saville
  */
  */
 public abstract class MessageNano {
 public abstract class MessageNano {
-    protected int cachedSize = -1;
+    protected volatile int cachedSize = -1;
 
 
     /**
     /**
      * Get the number of bytes required to encode this message.
      * Get the number of bytes required to encode this message.
@@ -61,9 +61,18 @@ public abstract class MessageNano {
      * using getCachedSize().
      * using getCachedSize().
      */
      */
     public int getSerializedSize() {
     public int getSerializedSize() {
-        // This is overridden if the generated message has serialized fields.
-        cachedSize = 0;
-        return 0;
+        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;
     }
     }
 
 
     /**
     /**

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

@@ -105,6 +105,12 @@ public class NanoTest extends TestCase {
     assertEquals(456, newMsg.d);
     assertEquals(456, newMsg.d);
     assertEquals(2, msg.nestedMsg.bb);
     assertEquals(2, msg.nestedMsg.bb);
     assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
     assertEquals(SimpleMessageNano.BAR, msg.defaultNestedEnum);
+
+    msg.nestedMsg = null;
+    assertTrue(msgSerializedSize != msg.getSerializedSize());
+
+    msg.clear();
+    assertEquals(0, msg.getSerializedSize());
   }
   }
 
 
   public void testRecursiveMessageNano() throws Exception {
   public void testRecursiveMessageNano() throws Exception {
@@ -143,6 +149,12 @@ public class NanoTest extends TestCase {
     assertEquals(3, newMsg.repeatedRecursiveMessageNano[0].id);
     assertEquals(3, newMsg.repeatedRecursiveMessageNano[0].id);
   }
   }
 
 
+  public void testMessageNoFields() {
+    SingleMessageNano msg = new SingleMessageNano();
+    assertEquals(0, msg.getSerializedSize());
+    assertEquals(0, MessageNano.toByteArray(msg).length);
+  }
+
   public void testNanoRequiredInt32() throws Exception {
   public void testNanoRequiredInt32() throws Exception {
     TestAllTypesNano msg = new TestAllTypesNano();
     TestAllTypesNano msg = new TestAllTypesNano();
     msg.id = 123;
     msg.id = 123;

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

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