blob: 6d8b6ec85b733db98db776956af8e8f5d4aa2e24 [file] [log] [blame]
Feng Xiaof157a562014-11-14 11:50:31 -08001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#ifndef GOOGLE_PROTOBUF_MAP_FIELD_H__
32#define GOOGLE_PROTOBUF_MAP_FIELD_H__
33
34#include <google/protobuf/stubs/atomicops.h>
35#include <google/protobuf/stubs/common.h>
36#include <google/protobuf/generated_message_reflection.h>
Jisi Liu885b6122015-02-28 14:51:22 -080037#include <google/protobuf/arena.h>
Feng Xiaof157a562014-11-14 11:50:31 -080038#include <google/protobuf/map_entry.h>
Jisi Liu885b6122015-02-28 14:51:22 -080039#include <google/protobuf/map_field_lite.h>
40#include <google/protobuf/map_type_handler.h>
Feng Xiaof157a562014-11-14 11:50:31 -080041#include <google/protobuf/message.h>
42#include <google/protobuf/repeated_field.h>
43#include <google/protobuf/unknown_field_set.h>
44
45
46namespace google {
47namespace protobuf {
48
49namespace internal {
50
51class ContendedMapCleanTest;
52class GeneratedMessageReflection;
53class MapFieldAccessor;
54
55// This class provides accesss to map field using reflection, which is the same
56// as those provided for RepeatedPtrField<Message>. It is used for internal
57// reflection implentation only. Users should never use this directly.
58class LIBPROTOBUF_EXPORT MapFieldBase {
59 public:
60 MapFieldBase()
Jisi Liu885b6122015-02-28 14:51:22 -080061 : arena_(NULL),
62 repeated_field_(NULL),
63 entry_descriptor_(NULL),
64 assign_descriptor_callback_(NULL),
65 state_(STATE_MODIFIED_MAP) {}
66 explicit MapFieldBase(Arena* arena)
67 : arena_(arena),
Feng Xiaof157a562014-11-14 11:50:31 -080068 repeated_field_(NULL),
69 entry_descriptor_(NULL),
70 assign_descriptor_callback_(NULL),
71 state_(STATE_MODIFIED_MAP) {}
72 virtual ~MapFieldBase();
73
74 // Returns reference to internal repeated field. Data written using
75 // google::protobuf::Map's api prior to calling this function is guarantted to be
76 // included in repeated field.
77 const RepeatedPtrFieldBase& GetRepeatedField() const;
78
79 // Like above. Returns mutable pointer to the internal repeated field.
80 RepeatedPtrFieldBase* MutableRepeatedField();
81
82 // Returns the number of bytes used by the repeated field, excluding
83 // sizeof(*this)
84 int SpaceUsedExcludingSelf() const;
85
86 protected:
87 // Gets the size of space used by map field.
88 virtual int SpaceUsedExcludingSelfNoLock() const;
89
90 // Synchronizes the content in Map to RepeatedPtrField if there is any change
91 // to Map after last synchronization.
92 void SyncRepeatedFieldWithMap() const;
93 virtual void SyncRepeatedFieldWithMapNoLock() const;
94
95 // Synchronizes the content in RepeatedPtrField to Map if there is any change
96 // to RepeatedPtrField after last synchronization.
97 void SyncMapWithRepeatedField() const;
98 virtual void SyncMapWithRepeatedFieldNoLock() const {}
99
100 // Tells MapFieldBase that there is new change to Map.
101 void SetMapDirty();
102
103 // Tells MapFieldBase that there is new change to RepeatedPTrField.
104 void SetRepeatedDirty();
105
106 // Provides derived class the access to repeated field.
107 void* MutableRepeatedPtrField() const;
108
109 // Creates descriptor for only one time.
110 void InitMetadataOnce() const;
111
112 enum State {
113 STATE_MODIFIED_MAP = 0, // map has newly added data that has not been
114 // synchronized to repeated field
115 STATE_MODIFIED_REPEATED = 1, // repeated field has newly added data that
116 // has not been synchronized to map
117 CLEAN = 2, // data in map and repeated field are same
118 };
119
Jisi Liu885b6122015-02-28 14:51:22 -0800120 Arena* arena_;
Feng Xiaof157a562014-11-14 11:50:31 -0800121 mutable RepeatedPtrField<Message>* repeated_field_;
122 // MapEntry can only be created from MapField. To create MapEntry, MapField
123 // needs to know its descriptor, because MapEntry is not generated class which
124 // cannot initialize its own descriptor by calling generated
125 // descriptor-assign-function. Thus, we need to register a callback to
126 // initialize MapEntry's descriptor.
127 const Descriptor** entry_descriptor_;
128 void (*assign_descriptor_callback_)();
129
130 mutable Mutex mutex_; // The thread to synchronize map and repeated field
131 // needs to get lock first;
132 mutable volatile Atomic32 state_; // 0: STATE_MODIFIED_MAP
133 // 1: STATE_MODIFIED_REPEATED
134 // 2: CLEAN
135
136 private:
137 friend class ContendedMapCleanTest;
138 friend class GeneratedMessageReflection;
139 friend class MapFieldAccessor;
140};
141
142// This class provides accesss to map field using generated api. It is used for
143// internal generated message implentation only. Users should never use this
144// directly.
Jisi Liu885b6122015-02-28 14:51:22 -0800145template <typename Key, typename T,
146 WireFormatLite::FieldType kKeyFieldType,
147 WireFormatLite::FieldType kValueFieldType,
148 int default_enum_value = 0>
149class LIBPROTOBUF_EXPORT MapField : public MapFieldBase,
150 public MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
151 default_enum_value> {
152 // Handlers for key/value wire type. Provide utilities to parse/serialize
153 // key/value.
154 typedef MapWireFieldTypeHandler<kKeyFieldType> KeyWireHandler;
155 typedef MapWireFieldTypeHandler<kValueFieldType> ValueWireHandler;
Feng Xiaof157a562014-11-14 11:50:31 -0800156
157 // Define key/value's internal stored type.
Jisi Liu885b6122015-02-28 14:51:22 -0800158 static const bool kIsKeyMessage = KeyWireHandler::kIsMessage;
159 static const bool kIsValMessage = ValueWireHandler::kIsMessage;
160 typedef typename KeyWireHandler::CppType KeyInternalType;
161 typedef typename ValueWireHandler::CppType ValueInternalType;
162 typedef typename MapIf<kIsKeyMessage, Key, KeyInternalType>::type KeyCpp;
163 typedef typename MapIf<kIsValMessage, T , ValueInternalType>::type ValCpp;
Feng Xiaof157a562014-11-14 11:50:31 -0800164
165 // Handlers for key/value's internal stored type.
166 typedef MapCppTypeHandler<KeyCpp> KeyHandler;
167 typedef MapCppTypeHandler<ValCpp> ValHandler;
168
169 // Define message type for internal repeated field.
Jisi Liu885b6122015-02-28 14:51:22 -0800170 typedef MapEntry<Key, T, kKeyFieldType, kValueFieldType, default_enum_value>
171 EntryType;
172 typedef MapEntryLite<Key, T, kKeyFieldType, kValueFieldType,
173 default_enum_value> EntryLiteType;
174
175 // Define abbreviation for parent MapFieldLite
176 typedef MapFieldLite<Key, T, kKeyFieldType, kValueFieldType,
177 default_enum_value> MapFieldLiteType;
Feng Xiaof157a562014-11-14 11:50:31 -0800178
179 // Enum needs to be handled differently from other types because it has
180 // different exposed type in google::protobuf::Map's api and repeated field's api. For
181 // details see the comment in the implementation of
182 // SyncMapWithRepeatedFieldNoLocki.
Jisi Liu885b6122015-02-28 14:51:22 -0800183 static const bool kIsValueEnum = ValueWireHandler::kIsEnum;
Feng Xiaof157a562014-11-14 11:50:31 -0800184 typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
185
186 public:
187 MapField();
Jisi Liu885b6122015-02-28 14:51:22 -0800188 explicit MapField(Arena* arena);
Feng Xiaof157a562014-11-14 11:50:31 -0800189 // MapField doesn't own the default_entry, which means default_entry must
190 // outlive the lifetime of MapField.
191 MapField(const Message* default_entry);
Jisi Liu885b6122015-02-28 14:51:22 -0800192 // For tests only.
193 MapField(Arena* arena, const Message* default_entry);
Feng Xiaof157a562014-11-14 11:50:31 -0800194 ~MapField();
195
196 // Accessors
197 const Map<Key, T>& GetMap() const;
198 Map<Key, T>* MutableMap();
199
200 // Convenient methods for generated message implementation.
201 int size() const;
202 void Clear();
Jisi Liu885b6122015-02-28 14:51:22 -0800203 void MergeFrom(const MapFieldLiteType& other);
204 void Swap(MapFieldLiteType* other);
Feng Xiaof157a562014-11-14 11:50:31 -0800205
206 // Allocates metadata only if this MapField is part of a generated message.
207 void SetEntryDescriptor(const Descriptor** descriptor);
208 void SetAssignDescriptorCallback(void (*callback)());
209
Feng Xiaof157a562014-11-14 11:50:31 -0800210 private:
Jisi Liu885b6122015-02-28 14:51:22 -0800211 typedef void DestructorSkippable_;
212
Feng Xiaof157a562014-11-14 11:50:31 -0800213 // MapField needs MapEntry's default instance to create new MapEntry.
214 void InitDefaultEntryOnce() const;
215
Jisi Liu885b6122015-02-28 14:51:22 -0800216 // Manually set default entry instance. For test only.
217 void SetDefaultEntryOnce(const EntryType* default_entry) const;
218
Feng Xiaof157a562014-11-14 11:50:31 -0800219 // Convenient methods to get internal google::protobuf::Map
220 const Map<Key, T>& GetInternalMap() const;
221 Map<Key, T>* MutableInternalMap();
222
223 // Implements MapFieldBase
224 void SyncRepeatedFieldWithMapNoLock() const;
225 void SyncMapWithRepeatedFieldNoLock() const;
226 int SpaceUsedExcludingSelfNoLock() const;
227
228 mutable const EntryType* default_entry_;
Feng Xiaof157a562014-11-14 11:50:31 -0800229
Jisi Liu885b6122015-02-28 14:51:22 -0800230 friend class ::google::protobuf::Arena;
231};
Feng Xiao6ae3bde2014-11-25 14:01:44 -0800232
Feng Xiaof157a562014-11-14 11:50:31 -0800233} // namespace internal
234} // namespace protobuf
235
236} // namespace google
237#endif // GOOGLE_PROTOBUF_MAP_FIELD_H__