aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Vizerai <jsking@google.com>2017-05-23 16:13:25 -0700
committerGravatar Vizerai <jsking@google.com>2017-05-23 16:13:25 -0700
commitc1947ef5700f4431b77728ab12be8186c1e58eb5 (patch)
tree9cb6f86623dc535522cc65e611e5e402557cc891
parentd74dbd3889d4cbd3f756d0d6392569bf358a88d8 (diff)
update
-rw-r--r--BUILD1
-rw-r--r--build.yaml1
-rw-r--r--config.w321
-rw-r--r--gRPC-Core.podspec2
-rwxr-xr-xgrpc.gemspec1
-rw-r--r--package.xml1
-rw-r--r--src/core/ext/census/intrusive_hash_map.c5
-rw-r--r--src/core/ext/census/intrusive_hash_map.h73
-rw-r--r--src/core/ext/census/intrusive_hash_map_internal.h46
-rw-r--r--test/core/census/intrusive_hash_map_test.c18
-rw-r--r--tools/doxygen/Doxyfile.core.internal1
-rw-r--r--tools/run_tests/generated/sources_and_headers.json2
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj1
-rw-r--r--vsprojects/vcxproj/grpc/grpc.vcxproj.filters3
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj1
-rw-r--r--vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters3
16 files changed, 107 insertions, 53 deletions
diff --git a/BUILD b/BUILD
index 4429e9a81f..bdea522ad1 100644
--- a/BUILD
+++ b/BUILD
@@ -299,6 +299,7 @@ grpc_cc_library(
"src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h",
"src/core/ext/census/intrusive_hash_map.h",
+ "src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
diff --git a/build.yaml b/build.yaml
index c0886ae4b4..d2ea16c8c2 100644
--- a/build.yaml
+++ b/build.yaml
@@ -28,6 +28,7 @@ filegroups:
- src/core/ext/census/gen/trace_context.pb.h
- src/core/ext/census/grpc_filter.h
- src/core/ext/census/intrusive_hash_map.h
+ - src/core/ext/census/intrusive_hash_map_internal.h
- src/core/ext/census/mlog.h
- src/core/ext/census/resource.h
- src/core/ext/census/rpc_metric_id.h
diff --git a/config.w32 b/config.w32
index 0d82f9d757..7c407e848a 100644
--- a/config.w32
+++ b/config.w32
@@ -299,6 +299,7 @@ if (PHP_GRPC != "no") {
"src\\core\\ext\\census\\grpc_filter.c " +
"src\\core\\ext\\census\\grpc_plugin.c " +
"src\\core\\ext\\census\\initialize.c " +
+ "src\\core\\ext\\census\\intrusive_hash_map.c " +
"src\\core\\ext\\census\\mlog.c " +
"src\\core\\ext\\census\\operation.c " +
"src\\core\\ext\\census\\placeholders.c " +
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 0762dfed2a..d9de2d78a0 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -464,6 +464,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/intrusive_hash_map.h',
+ 'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',
@@ -949,6 +950,7 @@ Pod::Spec.new do |s|
'src/core/ext/census/gen/trace_context.pb.h',
'src/core/ext/census/grpc_filter.h',
'src/core/ext/census/intrusive_hash_map.h',
+ 'src/core/ext/census/intrusive_hash_map_internal.h',
'src/core/ext/census/mlog.h',
'src/core/ext/census/resource.h',
'src/core/ext/census/rpc_metric_id.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 13bcd7dc40..b334efb0b5 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -380,6 +380,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/census/gen/trace_context.pb.h )
s.files += %w( src/core/ext/census/grpc_filter.h )
s.files += %w( src/core/ext/census/intrusive_hash_map.h )
+ s.files += %w( src/core/ext/census/intrusive_hash_map_internal.h )
s.files += %w( src/core/ext/census/mlog.h )
s.files += %w( src/core/ext/census/resource.h )
s.files += %w( src/core/ext/census/rpc_metric_id.h )
diff --git a/package.xml b/package.xml
index ece21f9468..9179ef238c 100644
--- a/package.xml
+++ b/package.xml
@@ -394,6 +394,7 @@
<file baseinstalldir="/" name="src/core/ext/census/gen/trace_context.pb.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/grpc_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map.h" role="src" />
+ <file baseinstalldir="/" name="src/core/ext/census/intrusive_hash_map_internal.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
diff --git a/src/core/ext/census/intrusive_hash_map.c b/src/core/ext/census/intrusive_hash_map.c
index 4a747c9137..e64e8086ca 100644
--- a/src/core/ext/census/intrusive_hash_map.c
+++ b/src/core/ext/census/intrusive_hash_map.c
@@ -27,8 +27,7 @@ static inline uint32_t chunked_vector_hasher(uint64_t key) {
/* Vector chunks are 1MiB divided by pointer size. */
static const size_t VECTOR_CHUNK_SIZE = (1 << 20) / sizeof(void *);
-/* Helper functions which return buckets from the chunked vector. These are
- meant for internal use only within the intrusive_hash_map data structure. */
+/* Helper functions which return buckets from the chunked vector. */
static inline void **get_mutable_bucket(const chunked_vector *buckets,
uint32_t index) {
if (index < VECTOR_CHUNK_SIZE) {
@@ -68,7 +67,7 @@ static void chunked_vector_clear(chunked_vector *vec) {
}
if (vec->rest_ != NULL) {
size_t rest_size = RestSize(vec);
- for (uint32_t i = 0; i < rest_size; ++i) {
+ for (size_t i = 0; i < rest_size; ++i) {
if (vec->rest_[i] != NULL) {
gpr_free(vec->rest_[i]);
}
diff --git a/src/core/ext/census/intrusive_hash_map.h b/src/core/ext/census/intrusive_hash_map.h
index 900e4368c9..f005cc3b82 100644
--- a/src/core/ext/census/intrusive_hash_map.h
+++ b/src/core/ext/census/intrusive_hash_map.h
@@ -17,21 +17,17 @@
#ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/useful.h>
-#include <stdbool.h>
-
-/* intrusive_hash_map is a fast chained hash table. It is almost always faster
- * than STL hash_map, since this hash map avoids malloc and free during insert
- * and erase. This hash map is faster than a dense hash map when the application
- * calls insert and erase more often than find. When the workload is dominated
- * by find() a dense hash map may be faster.
+#include "src/core/ext/census/intrusive_hash_map_internal.h"
+
+/* intrusive_hash_map is a fast chained hash table. This hash map is faster than
+ * a dense hash map when the application calls insert and erase more often than
+ * find. When the workload is dominated by find() a dense hash map may be
+ * faster.
*
* intrusive_hash_map uses an intrusive header placed within a user defined
- * struct. IHM_key MUST be set to a valid value before insertion into the hash
- * map or undefined behavior may occur. IHM_hash_link needs to be set to NULL
- * initially.
+ * struct. The header field IHM_key MUST be set to a valid value before
+ * insertion into the hash map or undefined behavior may occur. The header field
+ * IHM_hash_link MUST to be set to NULL initially.
*
* EXAMPLE USAGE:
*
@@ -53,6 +49,8 @@
* return item;
* }
*
+ * intrusive_hash_map hash_map;
+ * intrusive_hash_map_init(&hash_map, 4);
* string_item *new_item1 = make_string_item(10, "test1", 5);
* bool ok = intrusive_hash_map_insert(&hash_map, (hm_item *)new_item1);
*
@@ -61,9 +59,10 @@
*/
/* Hash map item. Stores key and a pointer to the actual object. A user defined
- * version of this can be passed in as long as the first 2 entries (key and
- * hash_link) are the same. Pointer to struct will need to be cast as
- * (hm_item *) when passed to hash map. This allows it to be intrusive. */
+ * version of this can be passed in provided the first 2 entries (key and
+ * hash_link) are the same. These entries must be first in the user defined
+ * struct. Pointer to struct will need to be cast as (hm_item *) when passed to
+ * hash map. This allows it to be intrusive. */
typedef struct hm_item {
uint64_t key;
struct hm_item *hash_link;
@@ -71,33 +70,12 @@ typedef struct hm_item {
} hm_item;
/* Macro provided for ease of use. This must be first in the user defined
- * struct. */
+ * struct (i.e. uint64_t key and hm_item * must be the first two elements in
+ * that order). */
#define INTRUSIVE_HASH_MAP_HEADER \
uint64_t IHM_key; \
struct hm_item *IHM_hash_link
-/* The chunked vector is a data structure that allocates buckets for use in the
- * hash map. ChunkedVector is logically equivalent to T*[N] (cast void* as
- * T*). It's internally implemented as an array of 1MB arrays to avoid
- * allocating large consecutive memory chunks. This is an internal data
- * structure that should never be accessed directly. */
-typedef struct chunked_vector {
- size_t size_;
- void **first_;
- void ***rest_;
-} chunked_vector;
-
-/* Core intrusive hash map data structure. All internal elements are managed by
- * functions and should not be altered manually. intrusive_hash_map_init()
- * must first be called before an intrusive_hash_map can be used. */
-typedef struct intrusive_hash_map {
- uint32_t num_items;
- uint32_t extend_threshold;
- uint32_t log2_num_buckets;
- uint32_t hash_mask;
- chunked_vector buckets;
-} intrusive_hash_map;
-
/* Index struct which acts as a pseudo-iterator within the hash map. */
typedef struct hm_index {
uint32_t bucket_index; // hash map bucket index.
@@ -110,7 +88,10 @@ inline bool hm_index_compare(const hm_index *A, const hm_index *B) {
return (A->item == B->item && A->bucket_index == B->bucket_index);
}
-/* Helper functions for iterating over the hash map. */
+/*
+ Helper functions for iterating over the hash map.
+ */
+
/* On return idx will contain an invalid index which is always equal to
* hash_map->buckets.size_ */
void intrusive_hash_map_end(const intrusive_hash_map *hash_map, hm_index *idx);
@@ -152,18 +133,18 @@ hm_item *intrusive_hash_map_erase(intrusive_hash_map *hash_map, uint64_t key);
* Otherwise, it will insert the new item and return true. */
bool intrusive_hash_map_insert(intrusive_hash_map *hash_map, hm_item *item);
-/* Clear entire contents of the hash map, but leaves internal data structure
- * untouched. Second argument takes a function pointer to a method that will
+/* Clears entire contents of the hash map, but leaves internal data structure
+ * untouched. Second argument takes a function pointer to a function that will
* free the object designated by the user and pointed to by hash_map->value. */
void intrusive_hash_map_clear(intrusive_hash_map *hash_map,
void (*free_object)(void *));
/* Erase all contents of hash map and free the memory. Hash map is invalid
* after calling this function and cannot be used until it has been
- * reinitialized (intrusive_hash_map_init()). takes a function pointer to a
- * method that will free the object designated by the user and pointed to by
- * hash_map->value.*/
+ * reinitialized (intrusive_hash_map_init()). This function takes a function
+ * pointer to a function that will free the object designated by the user and
+ * pointed to by hash_map->value. */
void intrusive_hash_map_free(intrusive_hash_map *hash_map,
void (*free_object)(void *));
-#endif
+#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_H
diff --git a/src/core/ext/census/intrusive_hash_map_internal.h b/src/core/ext/census/intrusive_hash_map_internal.h
new file mode 100644
index 0000000000..c0a3c6f59a
--- /dev/null
+++ b/src/core/ext/census/intrusive_hash_map_internal.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
+#define GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+#include <stdbool.h>
+
+/* The chunked vector is a data structure that allocates buckets for use in the
+ * hash map. ChunkedVector is logically equivalent to T*[N] (cast void* as
+ * T*). It's internally implemented as an array of 1MB arrays to avoid
+ * allocating large consecutive memory chunks. This is an internal data
+ * structure that should never be accessed directly. */
+typedef struct chunked_vector {
+ size_t size_;
+ void **first_;
+ void ***rest_;
+} chunked_vector;
+
+/* Core intrusive hash map data structure. All internal elements are managed by
+ * functions and should not be altered manually. */
+typedef struct intrusive_hash_map {
+ uint32_t num_items;
+ uint32_t extend_threshold;
+ uint32_t log2_num_buckets;
+ uint32_t hash_mask;
+ chunked_vector buckets;
+} intrusive_hash_map;
+
+#endif // GRPC_CORE_EXT_CENSUS_INTRUSIVE_HASH_MAP_INTERNAL_H
diff --git a/test/core/census/intrusive_hash_map_test.c b/test/core/census/intrusive_hash_map_test.c
index d35a01e103..a0a46ebadf 100644
--- a/test/core/census/intrusive_hash_map_test.c
+++ b/test/core/census/intrusive_hash_map_test.c
@@ -28,14 +28,17 @@
/* The initial size of an intrusive hash map will be 2 to this power. */
static const uint32_t kInitialLog2Size = 4;
+/* Simple object used for testing intrusive_hash_map. */
typedef struct object { uint64_t val; } object;
+/* Helper function to allocate and initialize object. */
static inline object *make_new_object(uint64_t val) {
object *obj = (object *)gpr_malloc(sizeof(object));
obj->val = val;
return obj;
}
+/* Wrapper struct for object. */
typedef struct ptr_item {
INTRUSIVE_HASH_MAP_HEADER;
object *obj;
@@ -51,8 +54,10 @@ static inline ptr_item *make_ptr_item(uint64_t key, uint64_t value) {
return new_item;
}
+/* Helper function to deallocate ptr_item. */
static void free_ptr_item(void *ptr) { gpr_free(((ptr_item *)ptr)->obj); }
+/* Simple string object used for testing intrusive_hash_map. */
typedef struct string_item {
INTRUSIVE_HASH_MAP_HEADER;
// User data.
@@ -60,6 +65,7 @@ typedef struct string_item {
uint16_t len;
} string_item;
+/* Helper function to allocate and initialize string object. */
static string_item *make_string_item(uint64_t key, const char *buf,
uint16_t len) {
string_item *item = (string_item *)gpr_malloc(sizeof(string_item));
@@ -70,6 +76,7 @@ static string_item *make_string_item(uint64_t key, const char *buf,
return item;
}
+/* Helper function for comparing two string objects. */
static bool compare_string_item(const string_item *A, const string_item *B) {
if (A->IHM_key != B->IHM_key || A->len != B->len)
return false;
@@ -90,7 +97,7 @@ void test_empty() {
intrusive_hash_map_free(&hash_map, NULL);
}
-void test_basic() {
+void test_single_item() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
@@ -113,7 +120,7 @@ void test_basic() {
intrusive_hash_map_free(&hash_map, &free_ptr_item);
}
-void test_basic2() {
+void test_two_items() {
intrusive_hash_map hash_map;
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
@@ -215,10 +222,12 @@ void test_stress() {
intrusive_hash_map_init(&hash_map, kInitialLog2Size);
size_t n = 0;
+ // Randomly add and insert entries 1000000 times.
for (uint64_t i = 0; i < 1000000; ++i) {
int op = rand() & 0x1;
switch (op) {
+ // Case 0 is insertion of entry.
case 0: {
uint64_t key = (uint64_t)(rand() % 10000);
ptr_item *item = make_ptr_item(key, key);
@@ -231,6 +240,7 @@ void test_stress() {
}
break;
}
+ // Case 1 is removal of entry.
case 1: {
uint64_t key = (uint64_t)(rand() % 10000);
ptr_item *item = (ptr_item *)intrusive_hash_map_find(&hash_map, key);
@@ -262,8 +272,8 @@ int main(int argc, char **argv) {
srand((unsigned)gpr_now(GPR_CLOCK_REALTIME).tv_nsec);
test_empty();
- test_basic();
- test_basic2();
+ test_single_item();
+ test_two_items();
test_reset_clear();
test_extend();
test_stress();
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 3d4bf7b467..15410dec01 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -885,6 +885,7 @@ src/core/ext/census/grpc_plugin.c \
src/core/ext/census/initialize.c \
src/core/ext/census/intrusive_hash_map.c \
src/core/ext/census/intrusive_hash_map.h \
+src/core/ext/census/intrusive_hash_map_internal.h \
src/core/ext/census/mlog.c \
src/core/ext/census/mlog.h \
src/core/ext/census/operation.c \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index ca42c430e6..97e079d8a8 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -7559,6 +7559,7 @@
"src/core/ext/census/gen/trace_context.pb.h",
"src/core/ext/census/grpc_filter.h",
"src/core/ext/census/intrusive_hash_map.h",
+ "src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.h",
"src/core/ext/census/resource.h",
"src/core/ext/census/rpc_metric_id.h",
@@ -7591,6 +7592,7 @@
"src/core/ext/census/initialize.c",
"src/core/ext/census/intrusive_hash_map.c",
"src/core/ext/census/intrusive_hash_map.h",
+ "src/core/ext/census/intrusive_hash_map_internal.h",
"src/core/ext/census/mlog.c",
"src/core/ext/census/mlog.h",
"src/core/ext/census/operation.c",
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 1c42774c31..1303366574 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -505,6 +505,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index c110037bc8..9f25a1c179 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -1460,6 +1460,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h">
+ <Filter>src\core\ext\census</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 8b6b8cbd15..ac403a7c48 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -470,6 +470,7 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\gen\trace_context.pb.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\grpc_filter.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h" />
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 69657eb65f..9fee2ec22b 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -1295,6 +1295,9 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>
+ <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\intrusive_hash_map_internal.h">
+ <Filter>src\core\ext\census</Filter>
+ </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h">
<Filter>src\core\ext\census</Filter>
</ClInclude>