diff --git a/CHANGELOG.md b/CHANGELOG.md index eaaf4bd..cd38f98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.4.0 + +- upgrade `parking_lot` to `0.10` (note that this bumps MSRV with `parking_lot` feature enabled to `1.36.0`). + ## 1.3.1 - remove unnecessary `F: fmt::Debug` bound from `impl fmt::Debug for Lazy`. diff --git a/Cargo.lock.min b/Cargo.lock.min index 3e89dbd..32bfc1e 100644 --- a/Cargo.lock.min +++ b/Cargo.lock.min @@ -1,281 +1,150 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "autocfg" -version = "0.1.2" +name = "aho-corasick" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = ["memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] name = "bitflags" -version = "1.0.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] name = "crossbeam-utils" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = ["cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.54" +version = "0.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "once_cell" -version = "0.2.0" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "rand_core" -version = "0.4.0" +name = "memchr" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] +name = "once_cell" +version = "1.3.1" +dependencies = ["crossbeam-utils 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "rand_os" -version = "0.1.3" +name = "parking_lot" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "rand_pcg" -version = "0.1.2" +name = "parking_lot_core" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "rand_xorshift" -version = "0.1.1" +name = "redox_syscall" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "rdrand" -version = "0.4.0" +name = "regex" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "redox_syscall" -version = "0.1.54" +name = "regex-syntax" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = ["ucd-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "scopeguard" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "scopeguard" +name = "smallvec" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "semver" -version = "0.9.0" +name = "thread_local" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] -name = "semver-parser" -version = "0.7.0" +name = "ucd-util" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallvec" -version = "0.6.9" +name = "utf8-ranges" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] +dependencies = ["winapi-i686-pc-windows-gnu 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-x86_64-pc-windows-gnu 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)"] [[package]] name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" +"checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989" +"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" -"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" -"checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" -"checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum crossbeam-utils 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6efda20eef4ccf2a862d442a1e0319d568f9133e16a085a1f8126fe9b6da852d" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +"checksum parking_lot_core 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +"checksum redox_syscall 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35a48131ab10dbeb17202bd1dcb9c9798963a58a50c9ec31640f237358832094" +"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" +"checksum regex-syntax 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bfaca88e749e19dffb60f77b55e5d87a872fac7e9e48598f7cf93b2d8c047b0a" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum ucd-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f3bf5cdf1df6b578c0947a94d4740bbb2b2afd1b898e33df1ff07b555a335e4" +"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" +"checksum winapi 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3ad91d846a4a5342c1fb7008d26124ee6cf94a3953751618577295373b32117" +"checksum winapi-i686-pc-windows-gnu 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a8e2ebfc883e2b1771c6482b1fb3c6831eab289ba391619a2d93a7356220f" +"checksum winapi-x86_64-pc-windows-gnu 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca29cb03c8ceaf20f8224a18a530938305e9872b1478ea24ff44b4f503a1d1d" diff --git a/Cargo.toml b/Cargo.toml index fa28791..3ad1649 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ exclude = ["*.png", "*.svg", "/Cargo.lock.min", "/.travis.yml", "/run-miri-tests # Uses parking_lot to implement once_cell::sync::OnceCell. # This makes not speed difference, but makes each OnceCell # for up to two bytes smaller, depending on the size of the T. -parking_lot = { version = "0.9.0", optional = true, default_features = false } +parking_lot = { version = "0.10.0", optional = true, default_features = false } [dev-dependencies] lazy_static = "1.0.0" diff --git a/examples/bench_acquire.rs b/examples/bench_acquire.rs index da539a7..1518047 100644 --- a/examples/bench_acquire.rs +++ b/examples/bench_acquire.rs @@ -1,6 +1,6 @@ -/// Benchmark the overhead that the synchronization of `OnceCell::get` causes. -/// We do some other operations that write to memory to get an imprecise but somewhat realistic -/// measurement. +//! Benchmark the overhead that the synchronization of `OnceCell::get` causes. +//! We do some other operations that write to memory to get an imprecise but somewhat realistic +//! measurement. use once_cell::sync::OnceCell; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -29,7 +29,7 @@ fn thread_main(i: usize) { let mut data = [i; 128]; let mut accum = 0usize; for _ in 0..N_ROUNDS { - let _value = CELL.get_or_init(|| i+1); + let _value = CELL.get_or_init(|| i + 1); let k = OTHER.fetch_add(data[accum & 0x7F] as usize, Ordering::Relaxed); for j in data.iter_mut() { *j = (*j).wrapping_add(accum); diff --git a/examples/test_synchronization.rs b/examples/test_synchronization.rs index 1438bf3..0d54f98 100644 --- a/examples/test_synchronization.rs +++ b/examples/test_synchronization.rs @@ -1,11 +1,11 @@ -/// Test if the OnceCell properly synchronizes. -/// Needs to be run in release mode. -/// -/// We create a `Vec` with `N_ROUNDS` of `OnceCell`s. All threads will walk the `Vec`, and race to -/// be the first one to initialize a cell. -/// Every thread adds the results of the cells it sees to an accumulator, which is compared at the -/// end. -/// All threads should end up with the same result. +//! Test if the OnceCell properly synchronizes. +//! Needs to be run in release mode. +//! +//! We create a `Vec` with `N_ROUNDS` of `OnceCell`s. All threads will walk the `Vec`, and race to +//! be the first one to initialize a cell. +//! Every thread adds the results of the cells it sees to an accumulator, which is compared at the +//! end. +//! All threads should end up with the same result. use once_cell::sync::OnceCell; diff --git a/src/imp_pl.rs b/src/imp_pl.rs index 3c5b1ec..d49eabd 100644 --- a/src/imp_pl.rs +++ b/src/imp_pl.rs @@ -1,6 +1,8 @@ use std::{ cell::UnsafeCell, + mem::{self, MaybeUninit}, panic::{RefUnwindSafe, UnwindSafe}, + ptr, sync::atomic::{AtomicBool, Ordering}, }; @@ -9,7 +11,7 @@ use parking_lot::{lock_api::RawMutex as _RawMutex, RawMutex}; pub(crate) struct OnceCell { mutex: Mutex, is_initialized: AtomicBool, - pub(crate) value: UnsafeCell>, + value: UnsafeCell>, } // Why do we need `T: Send`? @@ -28,7 +30,21 @@ impl OnceCell { OnceCell { mutex: Mutex::new(), is_initialized: AtomicBool::new(false), - value: UnsafeCell::new(None), + value: UnsafeCell::new(MaybeUninit::uninit()), + } + } + + fn as_ptr(&self) -> *const T { + unsafe { + let slot: &MaybeUninit = &*self.value.get(); + slot.as_ptr() + } + } + + fn as_mut_ptr(&self) -> *mut T { + unsafe { + let slot: &mut MaybeUninit = &mut *self.value.get(); + slot.as_mut_ptr() } } @@ -56,13 +72,62 @@ impl OnceCell { // - finally, if it returns Ok, we store the value and store the flag with // `Release`, which synchronizes with `Acquire`s. let value = f()?; - let slot: &mut Option = unsafe { &mut *self.value.get() }; - debug_assert!(slot.is_none()); - *slot = Some(value); + // Safe b/c we have a unique access and no panic may happen + // until the cell is marked as initialized. + unsafe { self.value.get().write(MaybeUninit::new(value)) }; self.is_initialized.store(true, Ordering::Release); } Ok(()) } + + /// Get the reference to the underlying value, without checking if the cell + /// is initialized. + /// + /// # Safety + /// + /// Caller must ensure that the cell is in initialized state, and that + /// the contents are acquired by (synchronized to) this thread. + pub(crate) unsafe fn get_unchecked(&self) -> &T { + debug_assert!(self.is_initialized()); + &*self.as_ptr() + } + + /// Gets the mutable reference to the underlying value. + /// Returns `None` if the cell is empty. + pub(crate) fn get_mut(&mut self) -> Option<&mut T> { + if self.is_initialized() { + // Safe b/c we have a unique access and value is initialized. + Some(unsafe { &mut *self.as_mut_ptr() }) + } else { + None + } + } + + /// Consumes this `OnceCell`, returning the wrapped value. + /// Returns `None` if the cell was empty. + pub(crate) fn into_inner(self) -> Option { + if !self.is_initialized() { + return None; + } + + // Safe b/c we have a unique access and value is initialized. + let value: T = unsafe { ptr::read(self.as_ptr()) }; + + // It's OK to `mem::forget` without dropping, because both `self.mutex` + // and `self.is_initialized` are not heap-allocated. + mem::forget(self); + + Some(value) + } +} + +impl Drop for OnceCell { + fn drop(&mut self) { + if self.is_initialized() { + // Safe b/c we have a unique access and value is initialized. + unsafe { ptr::drop_in_place(self.as_mut_ptr()) }; + } + } } /// Wrapper around parking_lot's `RawMutex` which has `const fn` new. @@ -92,9 +157,8 @@ impl Drop for MutexGuard<'_> { } #[test] -#[cfg(target_pointer_width = "64")] fn test_size() { use std::mem::size_of; - assert_eq!(size_of::>(), 3 * size_of::()); + assert_eq!(size_of::>(), 2 * size_of::() + size_of::()); } diff --git a/src/imp_std.rs b/src/imp_std.rs index f5a6ea5..84d1e5f 100644 --- a/src/imp_std.rs +++ b/src/imp_std.rs @@ -5,6 +5,7 @@ use std::{ cell::{Cell, UnsafeCell}, + hint::unreachable_unchecked, marker::PhantomData, panic::{RefUnwindSafe, UnwindSafe}, sync::atomic::{AtomicBool, AtomicUsize, Ordering}, @@ -21,7 +22,7 @@ pub(crate) struct OnceCell { // that far. It was stabilized in 1.36.0, so, if you are reading this and // it's higher than 1.46.0 outside, please send a PR! ;) (and do the same // for `Lazy`, while we are at it). - pub(crate) value: UnsafeCell>, + value: UnsafeCell>, } // Why do we need `T: Send`? @@ -106,6 +107,43 @@ impl OnceCell { }); res } + + /// Get the reference to the underlying value, without checking if the cell + /// is initialized. + /// + /// # Safety + /// + /// Caller must ensure that the cell is in initialized state, and that + /// the contents are acquired by (synchronized to) this thread. + pub(crate) unsafe fn get_unchecked(&self) -> &T { + debug_assert!(self.is_initialized()); + let slot: &Option = &*self.value.get(); + match slot { + Some(value) => value, + // This unsafe does improve performance, see `examples/bench`. + None => { + debug_assert!(false); + unreachable_unchecked() + } + } + } + + /// Gets the mutable reference to the underlying value. + /// Returns `None` if the cell is empty. + pub(crate) fn get_mut(&mut self) -> Option<&mut T> { + // Safe b/c we have a unique access. + unsafe { &mut *self.value.get() }.as_mut() + } + + /// Consumes this `OnceCell`, returning the wrapped value. + /// Returns `None` if the cell was empty. + #[inline] + pub(crate) fn into_inner(self) -> Option { + // Because `into_inner` takes `self` by value, the compiler statically + // verifies that it is not currently borrowed. + // So, it is safe to move out `Option`. + self.value.into_inner() + } } // Corresponds to `std::sync::Once::call_inner` diff --git a/src/lib.rs b/src/lib.rs index e7bd7f6..d1a227e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -170,7 +170,8 @@ equivalents with `RefCell` and `Mutex`. # Minimum Supported `rustc` Version -This crate's minimum supported `rustc` version is `1.31.1`. +This crate's minimum supported `rustc` version is `1.31.1` (or `1.36.0` with +`parking_lot` feature enabled). If only `std` feature is enabled, MSRV will be updated conservatively. When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable. @@ -570,7 +571,6 @@ pub mod sync { use std::{ cell::Cell, fmt, - hint::unreachable_unchecked, ops::{Deref, DerefMut}, panic::RefUnwindSafe, }; @@ -663,7 +663,7 @@ pub mod sync { /// method never blocks. pub fn get(&self) -> Option<&T> { if self.0.is_initialized() { - // Safe b/c checked is_initialize + // Safe b/c value is initialized. Some(unsafe { self.get_unchecked() }) } else { None @@ -674,28 +674,18 @@ pub mod sync { /// /// Returns `None` if the cell is empty. pub fn get_mut(&mut self) -> Option<&mut T> { - // Safe b/c we have a unique access. - unsafe { &mut *self.0.value.get() }.as_mut() + self.0.get_mut() } /// Get the reference to the underlying value, without checking if the /// cell is initialized. /// - /// Safety: + /// # Safety /// /// Caller must ensure that the cell is in initialized state, and that /// the contents are acquired by (synchronized to) this thread. pub unsafe fn get_unchecked(&self) -> &T { - debug_assert!(self.0.is_initialized()); - let slot: &Option = &*self.0.value.get(); - match slot { - Some(value) => value, - // This unsafe does improve performance, see `examples/bench`. - None => { - debug_assert!(false); - unreachable_unchecked() - } - } + self.0.get_unchecked() } /// Sets the contents of this cell to `value`. @@ -802,7 +792,7 @@ pub mod sync { } self.0.initialize(f)?; - // Safe b/c called initialize + // Safe b/c value is initialized. debug_assert!(self.0.is_initialized()); Ok(unsafe { self.get_unchecked() }) } @@ -823,9 +813,7 @@ pub mod sync { /// assert_eq!(cell.into_inner(), Some("hello".to_string())); /// ``` pub fn into_inner(self) -> Option { - // Because `into_inner` takes `self` by value, the compiler statically verifies - // that it is not currently borrowed. So it is safe to move out `Option`. - self.0.value.into_inner() + self.0.into_inner() } }