add LazyFieldLite.java
This commit is contained in:
parent
3b547d3526
commit
76b8a769ab
176
java/src/main/java/com/google/protobuf/LazyFieldLite.java
Normal file
176
java/src/main/java/com/google/protobuf/LazyFieldLite.java
Normal file
@ -0,0 +1,176 @@
|
||||
// Protocol Buffers - Google's data interchange format
|
||||
// Copyright 2008 Google Inc. All rights reserved.
|
||||
// http://code.google.com/p/protobuf/
|
||||
//
|
||||
// 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.
|
||||
|
||||
package com.google.protobuf;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores
|
||||
* the message in a ByteString initially and then parse it on-demand.
|
||||
*
|
||||
* LazyField is thread-compatible e.g. concurrent read are safe, however,
|
||||
* synchronizations are needed under read/write situations.
|
||||
*
|
||||
* This class is internal implementation detail, so you don't need to use it directly.
|
||||
*
|
||||
* @author xiangl@google.com (Xiang Li)
|
||||
*/
|
||||
public class LazyFieldLite {
|
||||
private ByteString bytes;
|
||||
private ExtensionRegistryLite extensionRegistry;
|
||||
private volatile boolean isDirty = false;
|
||||
|
||||
protected volatile MessageLite value;
|
||||
|
||||
public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) {
|
||||
this.extensionRegistry = extensionRegistry;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public LazyFieldLite() {
|
||||
}
|
||||
|
||||
public static LazyFieldLite fromValue(MessageLite value) {
|
||||
LazyFieldLite lf = new LazyFieldLite();
|
||||
lf.setValue(value);
|
||||
return lf;
|
||||
}
|
||||
|
||||
public boolean containsDefaultInstance() {
|
||||
return value == null && bytes == null;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
bytes = null;
|
||||
value = null;
|
||||
extensionRegistry = null;
|
||||
isDirty = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns message instance. At first time, serialized data is parsed by
|
||||
* {@code defaultInstance.getParserForType()}.
|
||||
*
|
||||
* @param defaultInstance its message's default instance. It's also used to get parser for the
|
||||
* message type.
|
||||
*/
|
||||
public MessageLite getValue(MessageLite defaultInstance) {
|
||||
ensureInitialized(defaultInstance);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* LazyField is not thread-safe for write access. Synchronizations are needed
|
||||
* under read/write situations.
|
||||
*/
|
||||
public MessageLite setValue(MessageLite value) {
|
||||
MessageLite originalValue = this.value;
|
||||
this.value = value;
|
||||
bytes = null;
|
||||
isDirty = true;
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
public void merge(LazyFieldLite value) {
|
||||
if (value.containsDefaultInstance()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytes == null) {
|
||||
this.bytes = value.bytes;
|
||||
} else {
|
||||
this.bytes.concat(value.toByteString());
|
||||
}
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) {
|
||||
this.bytes = bytes;
|
||||
this.extensionRegistry = extensionRegistry;
|
||||
isDirty = false;
|
||||
}
|
||||
|
||||
public ExtensionRegistryLite getExtensionRegistry() {
|
||||
return extensionRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Due to the optional field can be duplicated at the end of serialized
|
||||
* bytes, which will make the serialized size changed after LazyField
|
||||
* parsed. Be careful when using this method.
|
||||
*/
|
||||
public int getSerializedSize() {
|
||||
if (isDirty) {
|
||||
return value.getSerializedSize();
|
||||
}
|
||||
return bytes.size();
|
||||
}
|
||||
|
||||
public ByteString toByteString() {
|
||||
if (!isDirty) {
|
||||
return bytes;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (!isDirty) {
|
||||
return bytes;
|
||||
}
|
||||
if (value == null) {
|
||||
bytes = ByteString.EMPTY;
|
||||
} else {
|
||||
bytes = value.toByteString();
|
||||
}
|
||||
isDirty = false;
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ensureInitialized(MessageLite defaultInstance) {
|
||||
if (value != null) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (value != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (bytes != null) {
|
||||
value = defaultInstance.getParserForType()
|
||||
.parseFrom(bytes, extensionRegistry);
|
||||
} else {
|
||||
value = defaultInstance;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO(xiangl): Refactory the API to support the exception thrown from
|
||||
// lazily load messages.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user