summaryrefslogtreecommitdiffstats
path: root/vendor/countme
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/countme')
-rw-r--r--vendor/countme/.cargo-checksum.json1
-rw-r--r--vendor/countme/Cargo.lock168
-rw-r--r--vendor/countme/Cargo.toml48
-rw-r--r--vendor/countme/LICENSE-APACHE201
-rw-r--r--vendor/countme/LICENSE-MIT23
-rw-r--r--vendor/countme/README.md21
-rw-r--r--vendor/countme/examples/bench.rs69
-rw-r--r--vendor/countme/examples/bench_single_thread.rs77
-rw-r--r--vendor/countme/examples/print_at_exit.rs11
-rw-r--r--vendor/countme/src/imp.rs175
-rw-r--r--vendor/countme/src/lib.rs193
11 files changed, 987 insertions, 0 deletions
diff --git a/vendor/countme/.cargo-checksum.json b/vendor/countme/.cargo-checksum.json
new file mode 100644
index 000000000..21af6b7a5
--- /dev/null
+++ b/vendor/countme/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"4101e28468b7a3c7a051247ff0d55ea1f2ba58e303857a7a4d3bbaef5caf31cc","Cargo.toml":"5ba3effabbc65115689252c397fb98adb04ac0174819612ecc4e754cea3acf1b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"8a8a5d00072b2f1c99a47b50e45cd2604485d1ce1b242eb7dd2895d4c8ca8625","examples/bench.rs":"a081e78268bdfd452840aa23d607bdfac0f57197ca6af35a5832e888fa59ddd2","examples/bench_single_thread.rs":"3e39d60ccb10cbd2905eaa154592af7024c690432f62f09b8211f9d601b39ab0","examples/print_at_exit.rs":"86ace893845110a7035a6aaab71c43640729f374a4be8224e9c559c6fe52f457","src/imp.rs":"dee6f26cd36f8c4062371349f7ff6091aff236edf3e4cccf3d898386dcf0f5bd","src/lib.rs":"c993efcdef9eed3c149f19d2429c59849381c7f61b264741c4ca1696de918974"},"package":"7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"} \ No newline at end of file
diff --git a/vendor/countme/Cargo.lock b/vendor/countme/Cargo.lock
new file mode 100644
index 000000000..102108341
--- /dev/null
+++ b/vendor/countme/Cargo.lock
@@ -0,0 +1,168 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "countme"
+version = "3.0.1"
+dependencies = [
+ "dashmap",
+ "once_cell",
+ "rustc-hash",
+]
+
+[[package]]
+name = "dashmap"
+version = "5.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0834a35a3fce649144119e18da2a4d8ed12ef3862f47183fd46f625d072d96c"
+dependencies = [
+ "cfg-if",
+ "num_cpus",
+ "parking_lot",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.119"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
+
+[[package]]
+name = "lock_api"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
+dependencies = [
+ "scopeguard",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8380fe0152551244f0747b1bf41737e0f8a74f97a14ccefd1148187271634f3c"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "smallvec"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
+
+[[package]]
+name = "windows-sys"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
+dependencies = [
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
diff --git a/vendor/countme/Cargo.toml b/vendor/countme/Cargo.toml
new file mode 100644
index 000000000..675dea03a
--- /dev/null
+++ b/vendor/countme/Cargo.toml
@@ -0,0 +1,48 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "countme"
+version = "3.0.1"
+authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
+exclude = [".github/", "bors.toml", "rustfmt.toml"]
+description = "Counts the number of live instances of types"
+categories = ["development-tools::profiling"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/matklad/countme"
+
+[[example]]
+name = "print_at_exit"
+required-features = ["print_at_exit"]
+
+[[example]]
+name = "bench"
+required-features = ["enable"]
+
+[[example]]
+name = "bench_single_thread"
+required-features = ["enable"]
+[dependencies.dashmap]
+version = "5.0"
+optional = true
+
+[dependencies.once_cell]
+version = "1.5"
+optional = true
+
+[dependencies.rustc-hash]
+version = "1.1"
+optional = true
+
+[features]
+enable = ["dashmap", "once_cell", "rustc-hash"]
+print_at_exit = ["enable"]
diff --git a/vendor/countme/LICENSE-APACHE b/vendor/countme/LICENSE-APACHE
new file mode 100644
index 000000000..16fe87b06
--- /dev/null
+++ b/vendor/countme/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
diff --git a/vendor/countme/LICENSE-MIT b/vendor/countme/LICENSE-MIT
new file mode 100644
index 000000000..31aa79387
--- /dev/null
+++ b/vendor/countme/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/vendor/countme/README.md b/vendor/countme/README.md
new file mode 100644
index 000000000..42f3c7ea8
--- /dev/null
+++ b/vendor/countme/README.md
@@ -0,0 +1,21 @@
+A library to quickly get the live/total/max counts of allocated instances.
+
+```rust
+#[derive(Default)]
+struct Widget {
+ _c: countme::Count<Self>,
+ ...
+}
+
+let w1 = Widget::default();
+let w2 = Widget::default();
+let w3 = Widget::default();
+drop(w1);
+
+let counts = countme::get::<Widget>();
+assert_eq!(counts.live, 2);
+assert_eq!(counts.max_live, 3);
+assert_eq!(counts.total, 3);
+
+eprintln!("{}", countme::get_all());
+```
diff --git a/vendor/countme/examples/bench.rs b/vendor/countme/examples/bench.rs
new file mode 100644
index 000000000..1f9cc967f
--- /dev/null
+++ b/vendor/countme/examples/bench.rs
@@ -0,0 +1,69 @@
+use std::thread;
+
+use countme::{get, Count};
+
+#[derive(Default)]
+struct Foo {
+ _c: Count<Self>,
+}
+
+#[derive(Default)]
+struct Bar {
+ _c: Count<Self>,
+ _x: i32,
+}
+
+mod deeply {
+ pub(crate) mod nested {
+ pub(crate) mod module {
+ use countme::Count;
+
+ #[derive(Default)]
+ pub(crate) struct Quux {
+ _c: Count<Self>,
+ }
+ }
+ }
+}
+
+fn main() {
+ countme::enable(true);
+ let t = std::time::Instant::now();
+ let n = 5;
+ let m = 1_000_000;
+
+ let mut threads = Vec::new();
+ for _ in 0..n {
+ threads.push(thread::spawn(move || {
+ for _ in 0..m {
+ Foo::default();
+ }
+ }));
+ threads.push(thread::spawn(move || {
+ let mut xs = Vec::with_capacity(m);
+ for _ in 0..m {
+ xs.push(Bar::default())
+ }
+ }));
+ threads.push(thread::spawn(move || {
+ for _ in 0..m {
+ deeply::nested::module::Quux::default();
+ }
+ }));
+ }
+ for t in threads {
+ t.join().unwrap();
+ }
+
+ let foo = get::<Foo>();
+ assert_eq!(foo.total, m * n);
+ assert!(foo.max_live >= 1);
+ assert_eq!(foo.live, 0);
+
+ let bar = get::<Bar>();
+ assert_eq!(bar.total, m * n);
+ assert!(bar.max_live >= m);
+ assert_eq!(bar.live, 0);
+
+ println!("{:?}", t.elapsed());
+}
diff --git a/vendor/countme/examples/bench_single_thread.rs b/vendor/countme/examples/bench_single_thread.rs
new file mode 100644
index 000000000..ac147f861
--- /dev/null
+++ b/vendor/countme/examples/bench_single_thread.rs
@@ -0,0 +1,77 @@
+use countme::{get, Count};
+
+#[derive(Default)]
+struct Foo {
+ _c: Count<Self>,
+}
+
+#[derive(Default)]
+struct Bar {
+ _c: Count<Self>,
+ _x: i32,
+}
+
+mod deeply {
+ pub(crate) mod nested {
+ pub(crate) mod module {
+ use countme::Count;
+
+ #[derive(Default)]
+ pub(crate) struct Quux {
+ _c: Count<Self>,
+ }
+ }
+ }
+}
+
+fn main() {
+ countme::enable(true);
+ let t = std::time::Instant::now();
+ let n = 6;
+ let m = 2_000_000;
+
+ for _ in 0..n {
+ for _ in 0..m {
+ Foo::default();
+ }
+
+ let mut xs = Vec::with_capacity(m);
+ for _ in 0..m {
+ xs.push(Bar::default())
+ }
+
+ for _ in 0..m {
+ deeply::nested::module::Quux::default();
+ }
+
+ let fs = [
+ || drop(Foo::default()),
+ || drop(Bar::default()),
+ || drop(deeply::nested::module::Quux::default()),
+ || {
+ #[derive(Default)]
+ struct Local(Count<Self>);
+
+ Local::default();
+ },
+ ];
+ for i in 0..m {
+ fs[i % 4]();
+ }
+ }
+
+ let foo = get::<Foo>();
+ assert_eq!(foo.total, m * n + (m * n / 4));
+ assert_eq!(foo.max_live, 1);
+ assert_eq!(foo.live, 0);
+
+ let bar = get::<Bar>();
+ assert_eq!(bar.total, m * n + (m * n / 4));
+
+ // FIXME: why +1? This seems like a bug
+ // overreporting by 1 is not significant, but anyway
+ assert_eq!(bar.max_live, m + 1);
+ assert_eq!(bar.live, 0);
+
+ println!("{:?}", t.elapsed());
+}
diff --git a/vendor/countme/examples/print_at_exit.rs b/vendor/countme/examples/print_at_exit.rs
new file mode 100644
index 000000000..fd51e2288
--- /dev/null
+++ b/vendor/countme/examples/print_at_exit.rs
@@ -0,0 +1,11 @@
+#[derive(Default)]
+struct Widget {
+ _t: countme::Count<Self>,
+}
+
+fn main() {
+ let w1 = Widget::default();
+ let _w2 = Widget::default();
+ drop(w1);
+ let _w3 = Widget::default();
+}
diff --git a/vendor/countme/src/imp.rs b/vendor/countme/src/imp.rs
new file mode 100644
index 000000000..c1ace0da7
--- /dev/null
+++ b/vendor/countme/src/imp.rs
@@ -0,0 +1,175 @@
+use std::{
+ any::{type_name, TypeId},
+ cell::RefCell,
+ collections::HashMap,
+ hash::BuildHasherDefault,
+ os::raw::c_int,
+ sync::atomic::{AtomicBool, AtomicUsize, Ordering::Relaxed},
+ sync::Arc,
+};
+
+use dashmap::DashMap;
+use once_cell::sync::OnceCell;
+use rustc_hash::FxHasher;
+
+use crate::{AllCounts, Counts};
+
+static ENABLE: AtomicBool = AtomicBool::new(cfg!(feature = "print_at_exit"));
+
+type GlobalStore = DashMap<TypeId, Arc<Store>, BuildHasherDefault<FxHasher>>;
+
+#[inline]
+fn global_store() -> &'static GlobalStore {
+ static MAP: OnceCell<GlobalStore> = OnceCell::new();
+ MAP.get_or_init(|| {
+ if cfg!(feature = "print_at_exit") {
+ extern "C" {
+ fn atexit(f: extern "C" fn()) -> c_int;
+ }
+ extern "C" fn print_at_exit() {
+ eprint!("{}", get_all());
+ }
+ unsafe {
+ atexit(print_at_exit);
+ }
+ }
+
+ GlobalStore::default()
+ })
+}
+
+thread_local! {
+ static LOCAL: RefCell<HashMap<TypeId, Arc<Store>, BuildHasherDefault<FxHasher>>> = RefCell::default();
+}
+
+pub(crate) fn enable(yes: bool) {
+ ENABLE.store(yes, Relaxed);
+}
+
+#[inline]
+fn enabled() -> bool {
+ ENABLE.load(Relaxed)
+}
+
+#[inline]
+pub(crate) fn dec<T: 'static>() {
+ if enabled() {
+ do_dec(TypeId::of::<T>())
+ }
+}
+#[inline(never)]
+fn do_dec(key: TypeId) {
+ LOCAL.with(|local| {
+ // Fast path: we have needed store in thread local map
+ if let Some(store) = local.borrow().get(&key) {
+ store.dec();
+ return;
+ }
+
+ let global = global_store();
+
+ // Slightly slower: we don't have needed store in our thread local map,
+ // but some other thread has already initialized the needed store in the global map
+ if let Some(store) = global.get(&key) {
+ let store = store.value();
+ local.borrow_mut().insert(key, Arc::clone(store));
+ store.inc();
+ return;
+ }
+
+ // We only decrement counter after incremenrting it, so this line is unreachable
+ })
+}
+
+#[inline]
+pub(crate) fn inc<T: 'static>() {
+ if enabled() {
+ do_inc(TypeId::of::<T>(), type_name::<T>())
+ }
+}
+#[inline(never)]
+fn do_inc(key: TypeId, name: &'static str) {
+ LOCAL.with(|local| {
+ // Fast path: we have needed store in thread local map
+ if let Some(store) = local.borrow().get(&key) {
+ store.inc();
+ return;
+ }
+
+ let global = global_store();
+
+ let copy = match global.get(&key) {
+ // Slightly slower path: we don't have needed store in our thread local map,
+ // but some other thread has already initialized the needed store in the global map
+ Some(store) => {
+ let store = store.value();
+ store.inc();
+ Arc::clone(store)
+ }
+ // Slow path: we are the first to initialize both global and local maps
+ None => {
+ let store = global
+ .entry(key)
+ .or_insert_with(|| Arc::new(Store { name, ..Store::default() }))
+ .downgrade();
+ let store = store.value();
+
+ store.inc();
+ Arc::clone(store)
+ }
+ };
+
+ local.borrow_mut().insert(key, copy);
+ });
+}
+
+pub(crate) fn get<T: 'static>() -> Counts {
+ do_get(TypeId::of::<T>())
+}
+fn do_get(key: TypeId) -> Counts {
+ global_store().entry(key).or_default().value().read()
+}
+
+pub(crate) fn get_all() -> AllCounts {
+ let mut entries = global_store()
+ .iter()
+ .map(|entry| {
+ let store = entry.value();
+ (store.type_name(), store.read())
+ })
+ .collect::<Vec<_>>();
+ entries.sort_by_key(|(name, _counts)| *name);
+ AllCounts { entries }
+}
+
+#[derive(Default)]
+struct Store {
+ total: AtomicUsize,
+ max_live: AtomicUsize,
+ live: AtomicUsize,
+ name: &'static str,
+}
+
+impl Store {
+ fn inc(&self) {
+ self.total.fetch_add(1, Relaxed);
+ let live = self.live.fetch_add(1, Relaxed) + 1;
+ self.max_live.fetch_max(live, Relaxed);
+ }
+
+ fn dec(&self) {
+ self.live.fetch_sub(1, Relaxed);
+ }
+
+ fn read(&self) -> Counts {
+ Counts {
+ total: self.total.load(Relaxed),
+ max_live: self.max_live.load(Relaxed),
+ live: self.live.load(Relaxed),
+ }
+ }
+
+ fn type_name(&self) -> &'static str {
+ self.name
+ }
+}
diff --git a/vendor/countme/src/lib.rs b/vendor/countme/src/lib.rs
new file mode 100644
index 000000000..f89e63c5b
--- /dev/null
+++ b/vendor/countme/src/lib.rs
@@ -0,0 +1,193 @@
+//! A library to quickly get the live/total/max counts of allocated instances.
+//!
+//! # Example
+//!
+//! ```
+//! # if cfg!(not(feature = "enable")) { return; }
+//!
+//! #[derive(Default)]
+//! struct Widget {
+//! _c: countme::Count<Self>,
+//! }
+//!
+//! countme::enable(true);
+//!
+//! let w1 = Widget::default();
+//! let w2 = Widget::default();
+//! let w3 = Widget::default();
+//! drop(w1);
+//!
+//! let counts = countme::get::<Widget>();
+//! assert_eq!(counts.live, 2);
+//! assert_eq!(counts.max_live, 3);
+//! assert_eq!(counts.total, 3);
+//!
+//! eprintln!("{}", countme::get_all());
+//! ```
+//!
+//! # Configuration
+//!
+//! By default, the implementation compiles to no-ops. Therefore it is possible
+//! to include `Count` fields into library types.
+//!
+//! The `enable` cargo feature ungates the counting code. The feature can be
+//! enabled anywhere in the crate graph.
+//!
+//! At run-time, the counters are controlled with [`enable`] function. Counting
+//! is enabled by default if `print_at_exit` feature is enabled. Otherwise
+//! counting is disabled by default. Call `enable(true)` early in `main` to enable:
+//!
+//! ```rust
+//! fn main() {
+//! countme::enable(std::env::var("COUNTME").is_ok());
+//! }
+//! ```
+//!
+//! The code is optimized for the case where counting is not enabled at runtime
+//! (counting is a relaxed load and a branch to a function call).
+//!
+//! The `print_at_exit` Cargo feature uses `atexit` call to print final counts
+//! before the program exits (it also enables counting at runtime). Use it only
+//! when you can't modify the main to print counts -- `atexit` is not guaranteed
+//! to work with rust's runtime.
+#[cfg(feature = "enable")]
+mod imp;
+
+use std::{fmt, marker::PhantomData};
+
+#[derive(Debug, Clone, PartialEq, Eq, Default)]
+#[non_exhaustive]
+pub struct Counts {
+ /// The total number of tokens created.
+ pub total: usize,
+ /// The historical maximum of the `live` count.
+ pub max_live: usize,
+ /// The number of tokens which were created, but are not destroyed yet.
+ pub live: usize,
+}
+
+/// Store this inside your struct as `_c: countme::Count<Self>`.
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Count<T: 'static> {
+ ghost: PhantomData<fn(T)>,
+}
+
+impl<T: 'static> Default for Count<T> {
+ #[inline]
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<T: 'static> Clone for Count<T> {
+ #[inline]
+ fn clone(&self) -> Self {
+ Self::new()
+ }
+}
+
+impl<T: 'static> Count<T> {
+ /// Create new `Count`, incrementing the corresponding count.
+ #[inline]
+ pub fn new() -> Count<T> {
+ #[cfg(feature = "enable")]
+ imp::inc::<T>();
+ Count { ghost: PhantomData }
+ }
+}
+
+impl<T: 'static> Drop for Count<T> {
+ #[inline]
+ fn drop(&mut self) {
+ #[cfg(feature = "enable")]
+ imp::dec::<T>();
+ }
+}
+
+/// Enable or disable counting at runtime.
+///
+/// Counting is enabled by default if `print_at_exit` feature is enabled.
+/// Otherwise counting is disabled by default.
+///
+/// If neither `enable` nor `print_at_exit` features are enabled, then this function is noop.
+pub fn enable(_yes: bool) {
+ #[cfg(feature = "enable")]
+ imp::enable(_yes);
+}
+
+/// Returns the counts for the `T` type.
+#[inline]
+pub fn get<T: 'static>() -> Counts {
+ #[cfg(feature = "enable")]
+ {
+ return imp::get::<T>();
+ }
+ #[cfg(not(feature = "enable"))]
+ {
+ return Counts::default();
+ }
+}
+
+/// Returns a collection of counts for all types.
+pub fn get_all() -> AllCounts {
+ #[cfg(feature = "enable")]
+ {
+ return imp::get_all();
+ }
+ #[cfg(not(feature = "enable"))]
+ {
+ return AllCounts::default();
+ }
+}
+
+/// A collection of counts for all types.
+#[derive(Default, Clone, Debug)]
+pub struct AllCounts {
+ entries: Vec<(&'static str, Counts)>,
+}
+
+impl fmt::Display for AllCounts {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fn sep(mut n: usize) -> String {
+ let mut groups = Vec::new();
+ while n >= 1000 {
+ groups.push(format!("{:03}", n % 1000));
+ n /= 1000;
+ }
+ groups.push(n.to_string());
+ groups.reverse();
+ groups.join("_")
+ }
+
+ if self.entries.is_empty() {
+ return if cfg!(feature = "enable") {
+ writeln!(f, "all counts are zero")
+ } else {
+ writeln!(f, "counts are disabled")
+ };
+ }
+ let max_width =
+ self.entries.iter().map(|(name, _count)| name.chars().count()).max().unwrap_or(0);
+ for (name, counts) in &self.entries {
+ writeln!(
+ f,
+ "{:<max_width$} {:>12} {:>12} {:>12}",
+ name,
+ sep(counts.total),
+ sep(counts.max_live),
+ sep(counts.live),
+ max_width = max_width
+ )?;
+ }
+ writeln!(
+ f,
+ "{:<max_width$} {:>12} {:>12} {:>12}",
+ "",
+ "total",
+ "max_live",
+ "live",
+ max_width = max_width
+ )?;
+ Ok(())
+ }
+}