Compare commits
2478 Commits
boost-1.45.0
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e76b1cf68 | |||
| 22f29718e4 | |||
| f7c7f8fdd2 | |||
| 7fd94b9df7 | |||
| 1c0e54ee3e | |||
| 329022b23c | |||
| 47f5be3a3f | |||
| de2ac0ce33 | |||
| 42df4f2749 | |||
| dbe93c765c | |||
| ea4fc5e66d | |||
| 0e19223e5b | |||
| 8ee48fe909 | |||
| ef0b3a0cd8 | |||
| 44b669a71c | |||
| 554ce65a69 | |||
| c37d9a3bf1 | |||
| 4fcc6a9cab | |||
| 0d61746fa3 | |||
| 20559cbe5c | |||
| 6728ffcf6d | |||
| 9f5f8b1b48 | |||
| aedebff4e1 | |||
| 47fa9cd17e | |||
| a0e1bc295a | |||
| f5bd5bc3d0 | |||
| 630031706b | |||
| 9bc7876583 | |||
| b482890453 | |||
| bc764d34cf | |||
| a9da328e1d | |||
| 087f2052fc | |||
| 51a75c0fd0 | |||
| ce5033c4a0 | |||
| bcbb13e0cf | |||
| 7aac692162 | |||
| f1729bb8a1 | |||
| b4884b7201 | |||
| b0a13f896f | |||
| cb86544fcf | |||
| 6c97eabbb3 | |||
| 968c2e9c11 | |||
| 53a6566a98 | |||
| 9b1ec6cbce | |||
| 3f3b2128ec | |||
| d3e6be7356 | |||
| 423eb08f00 | |||
| 777f2084a3 | |||
| e5bf418c3d | |||
| 9d8beff688 | |||
| 91f63697a7 | |||
| 22344ab27f | |||
| d742ee3a3b | |||
| d881d4d5e2 | |||
| 15318f0e46 | |||
| e32f72d69c | |||
| e37e749b0b | |||
| b02d013d44 | |||
| 33dbd7cd76 | |||
| 8f382e874d | |||
| bce9b5927a | |||
| c6aa90651c | |||
| cddb7cb8b1 | |||
| a36a7327eb | |||
| d2dc503e4a | |||
| 0c7b51cc16 | |||
| 3f0f8efbba | |||
| 8d59040ece | |||
| 15d04295d6 | |||
| 866ab46385 | |||
| 4cd1827104 | |||
| 3bd7e93ac6 | |||
| 1d991d065e | |||
| 8782036a88 | |||
| f088a5b9b9 | |||
| 16386f586f | |||
| 59a7fa09ba | |||
| 8cbd9ad80a | |||
| b0ee2b5116 | |||
| adb91ac06d | |||
| 11322de29f | |||
| 0c90a84aa0 | |||
| aa16d1b8a9 | |||
| 6b65c8f230 | |||
| b445ff639d | |||
| 08187c7a1f | |||
| 6953014874 | |||
| 7b24cf6607 | |||
| 6f0a715541 | |||
| 85c7900339 | |||
| c0cd51bd2a | |||
| 73891c6ec8 | |||
| 82f4d9899c | |||
| cad3509a17 | |||
| 44582ecbb9 | |||
| 9e38e3c578 | |||
| d5d6a18298 | |||
| 88f8228079 | |||
| 31c3ce97de | |||
| 651f209e20 | |||
| d9d4ff1676 | |||
| 2ce456768d | |||
| 65d4a9cafa | |||
| 8d2a5c25ea | |||
| 49f0929466 | |||
| 0673c5653c | |||
| a3a1ab6ad2 | |||
| 7d639e2e86 | |||
| 32b9f06fe5 | |||
| 3d302980d4 | |||
| 1dc1962b8c | |||
| a0c7112652 | |||
| b031b61b94 | |||
| b9fe4ed789 | |||
| c707bcb6d8 | |||
| 771943e291 | |||
| 675e30bd95 | |||
| 2cab340749 | |||
| c3786357a6 | |||
| 33ee8ea302 | |||
| 583225ad9f | |||
| c16a3f2a4a | |||
| 1d93fa12a2 | |||
| f4f322b94d | |||
| 3299b31787 | |||
| 95a37b0d3d | |||
| 4d6ebc7eb3 | |||
| a0679e5ffe | |||
| b01f9ee15d | |||
| 215d8e82cb | |||
| 067884a4e2 | |||
| ca2a46f290 | |||
| d007a5a7bd | |||
| b0195297f0 | |||
| 52061a7c64 | |||
| 829a4a1620 | |||
| 6dd58f4e9c | |||
| a2ad7966ea | |||
| 9d897faece | |||
| 389e967484 | |||
| 0365be763a | |||
| fc3fca4264 | |||
| bf0ae6e63a | |||
| 9057369f93 | |||
| aec9c48cf4 | |||
| 3968ff0567 | |||
| 8170716156 | |||
| 651727508b | |||
| b3b4853dfa | |||
| 1f3980986d | |||
| 4e458f0054 | |||
| 8fe3ebc7b3 | |||
| cf298cba7f | |||
| d83efc5ea4 | |||
| ff9d08a917 | |||
| e1a30831fe | |||
| 34e5773a4a | |||
| c26137f2dd | |||
| 1264805a59 | |||
| bfb6520107 | |||
| ab867a65f4 | |||
| 5239b101e2 | |||
| c5f64ed1d3 | |||
| a06498f5ce | |||
| bcd8969b9a | |||
| bc7e77f239 | |||
| 66222eee6a | |||
| ee1974dc87 | |||
| 4918bb6b7e | |||
| e563c89b1c | |||
| ce076782fd | |||
| b206513a11 | |||
| bf4a5efd2d | |||
| 6b6dde4f97 | |||
| ac1a236de6 | |||
| d4adcd9b71 | |||
| c046b916f8 | |||
| 4be37cfdaf | |||
| 6994a37b23 | |||
| 6bf84067b3 | |||
| 48ff743d06 | |||
| 5339bf67d9 | |||
| 1979ce98a2 | |||
| a22c133c3d | |||
| f919ce532a | |||
| 30187f7743 | |||
| dd30162c9e | |||
| fde765c494 | |||
| 9c476ef72a | |||
| 470abf41d8 | |||
| a3626b5095 | |||
| 948151bd7d | |||
| f965298154 | |||
| 5a4d93a72d | |||
| bee4ed2e5f | |||
| bd24dfd284 | |||
| faf54eef0d | |||
| 97b52879f5 | |||
| 9a7d1d336a | |||
| 3fc18d56ac | |||
| 6bcf457b46 | |||
| 01b2369700 | |||
| fcb3f0e82a | |||
| 1e4deb10a1 | |||
| 6ee93f17e4 | |||
| 7e41e08a57 | |||
| 7a6c8eca09 | |||
| dce386068b | |||
| 7d39b68e46 | |||
| 79a59bce72 | |||
| 717048e868 | |||
| de8c2a5ad9 | |||
| 678f8802f4 | |||
| 704b3c7a4b | |||
| 671b68f4d1 | |||
| b2a4b22c89 | |||
| 2eebe157fd | |||
| 2b6cfe4f3c | |||
| 2f7bba0c21 | |||
| d65d9a65b7 | |||
| 67913ed99a | |||
| 0440cd3183 | |||
| 3a3148cc16 | |||
| f51070ab21 | |||
| ac5a99da31 | |||
| 6fed6ea5ad | |||
| c51c06492a | |||
| f604efe866 | |||
| e8ec858313 | |||
| bc8996559b | |||
| 449e1a30d3 | |||
| c2484f05f0 | |||
| f7e2132bdb | |||
| 07a8b2b14d | |||
| 2eac49f0ed | |||
| 6a8d7857e2 | |||
| ef34ec5e87 | |||
| 518a5d2e1e | |||
| 3ea8a768ca | |||
| 4b877d363a | |||
| 2395db7bb9 | |||
| 7327053eea | |||
| af19d99b70 | |||
| 64f9370fff | |||
| ca193de243 | |||
| 2914925b4d | |||
| bc37851725 | |||
| f89a31849c | |||
| ec945810eb | |||
| 68ddaba57a | |||
| c48c2afc56 | |||
| 01a5dd0dd1 | |||
| 300a8e61bd | |||
| 1d2be664a0 | |||
| e6b1ef9e1e | |||
| 4efb55146a | |||
| 8877d21237 | |||
| 44c50cd2ea | |||
| e7c1e1a56e | |||
| 9a22f8fbee | |||
| 51520de04b | |||
| 6e0f76f4c2 | |||
| 06aa4b5c19 | |||
| 332540c857 | |||
| fdedb6c957 | |||
| 7aaa2e9452 | |||
| 950e640fcf | |||
| 7874625c08 | |||
| 2ab4225473 | |||
| c5df4ec069 | |||
| 55d79204be | |||
| f5d5299b88 | |||
| 253a9bccf6 | |||
| 61f11a58ee | |||
| e78dc311e3 | |||
| a5748c2e8b | |||
| 146c5cb6be | |||
| c63a88032d | |||
| 3ad164267a | |||
| a9203ed93c | |||
| 16550ded0c | |||
| b4c75abca9 | |||
| a696bdecf6 | |||
| 8865a940fc | |||
| 2a28698c8c | |||
| 96f5983f88 | |||
| ddb1148a31 | |||
| ffcae204ee | |||
| f28527c4d8 | |||
| 528f7d4b12 | |||
| a140de4254 | |||
| f1bc948be8 | |||
| 3d640ac032 | |||
| ff10b287e2 | |||
| 4a416501c8 | |||
| bf06fa97e3 | |||
| fcf6fee0f6 | |||
| 8ddfc8ec7a | |||
| 5f249bc681 | |||
| dbd1a929e6 | |||
| 32ff2f145e | |||
| 63026fd320 | |||
| 6295c7f0d4 | |||
| c3879e238d | |||
| 9260bff8f8 | |||
| f48fc70f4b | |||
| 48f703132e | |||
| 69ee0039e0 | |||
| add01e2dfd | |||
| 4b4db3dfb3 | |||
| 81480feeb4 | |||
| d615a08f76 | |||
| dacc1c8234 | |||
| 511e2b3272 | |||
| bcf5d0cf13 | |||
| 80a1904d92 | |||
| 21afc69894 | |||
| c90b72a643 | |||
| c2c34f96a3 | |||
| 69ba1c7c00 | |||
| ba25041fc8 | |||
| 02197674f4 | |||
| f0fe62d6ab | |||
| 53328766b9 | |||
| 5b775345ba | |||
| 99b0868283 | |||
| 1c98a4a8f1 | |||
| bf73366117 | |||
| 719394c522 | |||
| 03fccc1947 | |||
| 814264082f | |||
| 70e3dc4628 | |||
| b72dbef1a9 | |||
| 26924c73b9 | |||
| 23e720a968 | |||
| 4fb7751b55 | |||
| 3c0fb0fa1b | |||
| 3fe0807ae9 | |||
| dfb4f2a28a | |||
| cc4cfc7ef2 | |||
| a9bf367d6e | |||
| 2ea0dbf30e | |||
| 40c4d456f3 | |||
| 011b7a5969 | |||
| c52ad849ea | |||
| 615ce1e9b6 | |||
| bee9a3cb1a | |||
| 081932221f | |||
| 135c9586af | |||
| 187fd3e71e | |||
| 0959df1896 | |||
| 7833a8359d | |||
| 212c6a1e4d | |||
| d7acb7e8b8 | |||
| 0bc4f2c4b9 | |||
| 2b612ed120 | |||
| a7c15e86fc | |||
| 4c117ab20a | |||
| e9c6a0fef5 | |||
| ac216a93c8 | |||
| e49fef5f9a | |||
| 26ab9ff584 | |||
| 1e92d9f545 | |||
| 2cf72093b1 | |||
| 88d4d64edf | |||
| 7f7e577e77 | |||
| 80d7203d78 | |||
| 5dfed4deec | |||
| e08f9f11a1 | |||
| c304284773 | |||
| 0e8affcc07 | |||
| ba00dbd65a | |||
| c214fb44a3 | |||
| c704788718 | |||
| a91efeb237 | |||
| 7812b26d3a | |||
| 8bd07e17c3 | |||
| b3c0368ab5 | |||
| 37edc392a5 | |||
| fb403bc233 | |||
| 910b8de697 | |||
| 3aff995ae0 | |||
| 68c018fda6 | |||
| a9ad06139e | |||
| 9a0e5e9ea8 | |||
| b1a52d0236 | |||
| 1723358298 | |||
| 6bf0e93a41 | |||
| 0e5ef25a69 | |||
| ab84a922cf | |||
| d8bc38f154 | |||
| ecd4a82ed5 | |||
| 0898219edc | |||
| d9b62d24dc | |||
| b771278813 | |||
| 2226a7238d | |||
| 00c6a93a56 | |||
| 8ea1cbbd64 | |||
| 81a47ca88d | |||
| c54151769f | |||
| e73d5ecdd1 | |||
| 8a4e987030 | |||
| 8544d9f3c8 | |||
| ed80cb14e2 | |||
| 91eb2ddbd1 | |||
| 3bd28dc3d7 | |||
| e4d2da40f2 | |||
| a004e71dd0 | |||
| ddcab1c171 | |||
| e3cbf03f47 | |||
| f8fbbc3b76 | |||
| 52bf2bf7a2 | |||
| cf39fc4c38 | |||
| 1309361a02 | |||
| 946491489e | |||
| 19202d2a8d | |||
| 3be466966d | |||
| d22787c218 | |||
| b86dee9a18 | |||
| 863984a7c8 | |||
| e9b3ad4a5f | |||
| e00d700457 | |||
| 53e20a2a1b | |||
| af4cdf8fab | |||
| 7003e91d44 | |||
| e86bb5cce2 | |||
| 6a4728add0 | |||
| f02afbc815 | |||
| 6399dfd1e4 | |||
| f468fb77e0 | |||
| 5e316ebc88 | |||
| 0c90585511 | |||
| 13b4fd7133 | |||
| 27b4c62bd2 | |||
| 846de7ca82 | |||
| 62cf58d1ca | |||
| 4482031329 | |||
| 7b1af37b9c | |||
| 1c48f665ea | |||
| e4072747bb | |||
| ce674c8007 | |||
| 45ebc1e555 | |||
| 02c3bd4072 | |||
| 5f4172c13f | |||
| 40c5c6907a | |||
| 8dbe380d6c | |||
| 37ff9de0db | |||
| ae9f35073b | |||
| a85df27d4c | |||
| 88c70b885d | |||
| 240f5f94b1 | |||
| 7415721f7d | |||
| 8b5539756b | |||
| 49ac1035bb | |||
| d085c40541 | |||
| 99d5b9b1bb | |||
| ad86f9211b | |||
| d9515fdc2f | |||
| eedbc6bcf7 | |||
| 297fb2e8c4 | |||
| 99eab2dfb1 | |||
| 1070c9b69e | |||
| 9e6b5a7e43 | |||
| e1f11e840c | |||
| f2d4f1968b | |||
| 4a7116b996 | |||
| 41584e73d9 | |||
| 52453cb5a4 | |||
| 44b918896d | |||
| ff356ac083 | |||
| 3064801a89 | |||
| e9d9f19e76 | |||
| 9b85c38e37 | |||
| 0b2829c793 | |||
| a9c2d1daa5 | |||
| d29815b3a8 | |||
| 7ed7878278 | |||
| 4c927cd2f2 | |||
| 2fae05ed31 | |||
| 41abb96d83 | |||
| 63f51e7c41 | |||
| ba4f321934 | |||
| 68563fab72 | |||
| d8e9503869 | |||
| 86e998cbc7 | |||
| ce722e4d56 | |||
| 77eaab4803 | |||
| 96562f4c3b | |||
| d66ceaf7fe | |||
| 2e44769247 | |||
| e64fd45760 | |||
| 454fc7501e | |||
| a89c62728a | |||
| 1d8c0f91f8 | |||
| 25ba8e4dfc | |||
| fb4437219f | |||
| 0d1fdae84c | |||
| c5debf11cf | |||
| 9e4f89aa43 | |||
| 12935eb695 | |||
| 2386188d69 | |||
| e4b32f7f5e | |||
| 3df435d4d3 | |||
| ed076facc4 | |||
| b09c5bdcf0 | |||
| 6abb94bb68 | |||
| d2b1f095c8 | |||
| 3d34571654 | |||
| d683b3ac3e | |||
| e16a8737f4 | |||
| 8f348aea26 | |||
| 9a8ba2bdff | |||
| 3aaefdcc78 | |||
| ca59ed8c50 | |||
| ff78ef25c0 | |||
| ec487b5c6c | |||
| 0a03ed8170 | |||
| 5881dcc2b2 | |||
| 2070cbe2cc | |||
| 8198b9c57c | |||
| c35e9fc631 | |||
| f244ba55de | |||
| 5e225fe46c | |||
| 06535e518e | |||
| 81584c22cf | |||
| 83040211e8 | |||
| 4ed301df97 | |||
| 8010f506a6 | |||
| 840ea1ce5c | |||
| 447306bfb9 | |||
| 4569c1bec0 | |||
| 37ad547e18 | |||
| e037ee8d82 | |||
| 9bbadfdb34 | |||
| c1b63f68c8 | |||
| 0590e3bf8c | |||
| 8f17f5f548 | |||
| 3a8bea9e1d | |||
| b33b354818 | |||
| b08837b93e | |||
| b3b840df30 | |||
| 2ef47f0813 | |||
| 27f5513911 | |||
| a5100a9d35 | |||
| ccbc639677 | |||
| 18725a682d | |||
| dac1135199 | |||
| ead55a8938 | |||
| 8f39001ff0 | |||
| 8b056b902e | |||
| 5724adbbe9 | |||
| 1c5640cfbe | |||
| 4d982e133e | |||
| 1bf193b8fc | |||
| 7faec20f26 | |||
| ced8b45add | |||
| 15c9bc40f7 | |||
| 9aedb95296 | |||
| e56cb4418c | |||
| 1ae21c6d1a | |||
| 82acad3794 | |||
| c50461528c | |||
| bd08e49255 | |||
| dbba3cec7b | |||
| 6c5b5b3186 | |||
| 47dd02a4b3 | |||
| 8429d1a6aa | |||
| 86d3f9f632 | |||
| 48e92afd92 | |||
| 5a5c31de35 | |||
| 088941dc7b | |||
| 5f6f1691e5 | |||
| 45d6c07be6 | |||
| 5c63cd2bdb | |||
| 86318c1e88 | |||
| 0ff1fa0f6e | |||
| d90bf0c438 | |||
| dc63438e22 | |||
| 0a3ac26f00 | |||
| c64ed1caa3 | |||
| efc33b18be | |||
| c189d8d5e8 | |||
| 886227db3b | |||
| 719eb90d03 | |||
| fadb686bc5 | |||
| aebefaef0d | |||
| 63a564e8ff | |||
| 16c1593368 | |||
| 53580a3070 | |||
| d26aeed68f | |||
| 73eefd2b5d | |||
| 3df600d069 | |||
| a1adacdfe2 | |||
| f405fa9118 | |||
| 7b5d6e7c29 | |||
| 7d0ba7178e | |||
| df5e2c3aca | |||
| 343e344582 | |||
| 34ed463bea | |||
| 5986f75d16 | |||
| b08810c0c4 | |||
| 7c608ae7bc | |||
| d51cee35d5 | |||
| d0289b4c7b | |||
| bc7ba9cb3b | |||
| 6b10c8a4d3 | |||
| b9805c7309 | |||
| 844460fd22 | |||
| a600278d27 | |||
| 4398ffe8c9 | |||
| eed1eeedeb | |||
| 8c0c230f78 | |||
| e96ec1e79a | |||
| be7dd51fab | |||
| 4dec95840b | |||
| d44fb36581 | |||
| 9d3bbe27db | |||
| 13ed4afc95 | |||
| b3f54e74a7 | |||
| d6374e2718 | |||
| 74156b6b06 | |||
| 965048d3e6 | |||
| 36dfe6b98b | |||
| e4e89bdbde | |||
| 85a9d8d81d | |||
| b21ad13bbb | |||
| f0d10308e3 | |||
| f240e587cb | |||
| 2a7dc9e40e | |||
| 99b8d0063b | |||
| c6aff9278a | |||
| 129497133e | |||
| eaa9ff0cec | |||
| fa735864a3 | |||
| 0ce180e19b | |||
| e578b7eee3 | |||
| 1844695b0c | |||
| 54b9adbdbc | |||
| 8b71656cd7 | |||
| a858ef5688 | |||
| 18395c8d21 | |||
| e68ec5c9a9 | |||
| d3b264345d | |||
| f1e1733c06 | |||
| 66ffbdb881 | |||
| f7f5466ed2 | |||
| 83410fcabe | |||
| 1ee91d494d | |||
| e8fe550d6c | |||
| 5b0fe7f655 | |||
| ba439437bf | |||
| aa6eef135e | |||
| 1dd085daaa | |||
| 2a8f50bcb7 | |||
| 866c58a879 | |||
| c9a75a56c2 | |||
| e1861aa3d9 | |||
| 242c7cb93a | |||
| 0597463902 | |||
| 14d80725eb | |||
| a74962bc3c | |||
| cafa1f2278 | |||
| 40d5097d99 | |||
| 958aea3a61 | |||
| 6846eb53fd | |||
| 3b3ba7d6f7 | |||
| 22135bd845 | |||
| 141550f585 | |||
| d750b39e1e | |||
| 055587acf4 | |||
| 0f8dd003a3 | |||
| 9bc471310e | |||
| e56aac2e98 | |||
| 09a3275357 | |||
| a3c1e643dc | |||
| 955f94350b | |||
| 1955e4f36a | |||
| 644295db3a | |||
| 0391b6dafc | |||
| c646f3e3ca | |||
| 0e9523a0a4 | |||
| 24d8449831 | |||
| 59d0accce0 | |||
| 61aedca940 | |||
| 3fb516367f | |||
| 7d77f1d478 | |||
| 7572de875c | |||
| 63d907cde7 | |||
| f0037d336d | |||
| 8b14b7cddc | |||
| 6c60524fb7 | |||
| 8b1dcd3da3 | |||
| 0e980577b0 | |||
| 1f4244ec27 | |||
| dfbff823a9 | |||
| b85e17085f | |||
| 0a879c1063 | |||
| 01d508b6af | |||
| 7709950111 | |||
| 1ede59e662 | |||
| bf2b521789 | |||
| ee1515189b | |||
| eb33ad3e3f | |||
| 0ad6ccb0b9 | |||
| 0ab4e12502 | |||
| c8910e8007 | |||
| 2043f98593 | |||
| 260b573d8d | |||
| 4ac3dcc90c | |||
| 75ea43823e | |||
| b1d43d3ca5 | |||
| 534170a942 | |||
| 7befee3bd6 | |||
| 01deb2fd61 | |||
| 91eddbabe8 | |||
| 47e205487d | |||
| 2c1c99407e | |||
| 6be2bf89b6 | |||
| 5eda445db0 | |||
| 63f07daa88 | |||
| 7040c57750 | |||
| 9716731864 | |||
| 0bcd46a485 | |||
| 46a2cd109f | |||
| 808f8e659a | |||
| 8ed05de91c | |||
| 1a02fca5c4 | |||
| d036994237 | |||
| 8d4816eac7 | |||
| 46fc4f9f4d | |||
| 725993ab95 | |||
| ffa5e6f805 | |||
| 84206ebf8f | |||
| 0398afae9b | |||
| 79dc3bb6d4 | |||
| 879de5fab8 | |||
| 89ccb49165 | |||
| 70a980a980 | |||
| c895dd7192 | |||
| ea71597053 | |||
| 324fa793fd | |||
| 39d53a0bfc | |||
| 20ea4a77a7 | |||
| 53a897008a | |||
| ee8f2b991f | |||
| 5aff5b943f | |||
| 108d4535e0 | |||
| 2102031b93 | |||
| 5b92827b68 | |||
| e2f4303319 | |||
| c37081b4a2 | |||
| fd48672fd1 | |||
| 530437c21b | |||
| 2949b37490 | |||
| 867e60113b | |||
| 551456c0c5 | |||
| 7857582ea2 | |||
| 1d99854979 | |||
| e482947b20 | |||
| 5a4071d4f0 | |||
| c30e93544d | |||
| 99bd9d9d31 | |||
| 4310809025 | |||
| 0d8c02ba0e | |||
| d3985f87b3 | |||
| 3e4546465b | |||
| 79379a4049 | |||
| 71b860d6ae | |||
| 7c0a826815 | |||
| a7156026b3 | |||
| 787b1a9887 | |||
| 6e6ad354dd | |||
| 4bbaa0f710 | |||
| a3ef272a9e | |||
| 189e551dc7 | |||
| fdd5fe3b40 | |||
| a0652c2eda | |||
| 13e065466a | |||
| 300f5554e5 | |||
| d3914d7101 | |||
| 3b592a3dd4 | |||
| 2068cf8d5b | |||
| 097f4fac0b | |||
| 5327fec080 | |||
| 8f02e43ba4 | |||
| d0fc14b8c5 | |||
| 56b3700683 | |||
| cf643fad2a | |||
| 5386033e67 | |||
| d1e565dbf3 | |||
| acf8ddc4b7 | |||
| 575e5eafb0 | |||
| bce031f42b | |||
| 5e5addd82d | |||
| 0937f6443c | |||
| 90f2f0f67d | |||
| 772e1e7fa0 | |||
| 120fe90934 | |||
| 1dc949b2b5 | |||
| 4593d733a2 | |||
| 5e639a97a4 | |||
| fb315252b3 | |||
| d12ed06c3d | |||
| 49fc08b934 | |||
| 4f0edf9013 | |||
| 2afd1c5c9a | |||
| 492df9c9c6 | |||
| e29bf7a4a0 | |||
| 7db310f6d2 | |||
| 1f781a407e | |||
| ef54c6bd14 | |||
| fb1b1dfe2d | |||
| 222f0a737d | |||
| 6c0d121e5b | |||
| 955dab4637 | |||
| 375d7157b6 | |||
| 01053738eb | |||
| b75cd48899 | |||
| d8f226d429 | |||
| 627ffe4ed7 | |||
| 2adab2be61 | |||
| e0b680ac29 | |||
| ad1e3a49a5 | |||
| 1d15067ef2 | |||
| 8a3e5dd918 | |||
| 2aa62c63c1 | |||
| c9d1b6009e | |||
| 1d553447a0 | |||
| 703f8d1065 | |||
| fe32f153a2 | |||
| 59f4da0a47 | |||
| 99ad45ed77 | |||
| d93875a65e | |||
| c1d5902911 | |||
| 0ac4aeca50 | |||
| 776935f24d | |||
| 2f048ea6ac | |||
| f3353c9be3 | |||
| 3d07c33efe | |||
| 8a1562cc78 | |||
| 4de1be8911 | |||
| 46065065be | |||
| 8e42367a62 | |||
| d13a9dcaaf | |||
| 64cb43ce32 | |||
| c9340390b0 | |||
| c76f44a8b3 | |||
| 2290375515 | |||
| a200af610f | |||
| 2cb1d2bdf0 | |||
| ac2bc8d615 | |||
| 0d6ebb4d2f | |||
| 27c386d47b | |||
| cf6f4023bb | |||
| aa41ab4195 | |||
| 6e4e5ead03 | |||
| eb5351b2c6 | |||
| 599dee204f | |||
| 6b1d2f13da | |||
| b0f6bb128f | |||
| 0389e0bc16 | |||
| 9246c30178 | |||
| bb6b57d1a4 | |||
| 4fa61b98eb | |||
| 5535faf3cc | |||
| ec389cdecd | |||
| 7c5bad60c6 | |||
| cc75360f4c | |||
| 3a0b752363 | |||
| 63eaed843f | |||
| 0b575dc983 | |||
| b8d4df2b5c | |||
| 3bf28d7b61 | |||
| acc7f0ce5c | |||
| 1532e301d1 | |||
| e663812f24 | |||
| 9da61e9050 | |||
| 1de8801c08 | |||
| e16537d244 | |||
| 14c190223c | |||
| e3c91ad812 | |||
| 454cb24cc8 | |||
| 5e24f6ef22 | |||
| d02d4094e6 | |||
| 9a03d1e904 | |||
| 3683b43242 | |||
| fc5c8c3669 | |||
| df32d79e8a | |||
| aefb5dd66a | |||
| f85e04ef31 | |||
| 8c58ffe546 | |||
| d538f6184c | |||
| 7339f4264a | |||
| 87674d000b | |||
| 6227ae49a7 | |||
| c39ed8a5cf | |||
| d4f7939aae | |||
| fc7b5573c1 | |||
| 1c14bc1215 | |||
| 4399e8b360 | |||
| 3f9bd00f01 | |||
| 05b3025c0e | |||
| becd166e66 | |||
| 006f62047b | |||
| 334dcb91ac | |||
| df7792040c | |||
| 57ea45cb8f | |||
| 4a8d687778 | |||
| ccd40d0c44 | |||
| 35118b5a71 | |||
| 858737fd88 | |||
| 648fb7b99d | |||
| 59c84cb744 | |||
| becd6078b3 | |||
| e163aa465c | |||
| 3b1f635926 | |||
| 7abd7bb36d | |||
| 545ad4f7ad | |||
| c42d86ac0d | |||
| 316eeea983 | |||
| f2afbe9f85 | |||
| e9a94cb62a | |||
| 91f5925c41 | |||
| 0bdfa3c39e | |||
| 09f0b7c0a8 | |||
| 72bca09429 | |||
| 58b78f8ff0 | |||
| 1ff2dc4042 | |||
| 05f9668597 | |||
| c7836659d1 | |||
| c4cc805063 | |||
| 9e2bf3681f | |||
| 77f265a678 | |||
| 6bda467942 | |||
| 1fa2e84774 | |||
| 7caab66011 | |||
| 69aff6f776 | |||
| 505a08cf95 | |||
| f776ffa008 | |||
| a4c38c02c8 | |||
| 889a81f034 | |||
| ad96ea632e | |||
| 2955a966cf | |||
| 3fbaf21b8c | |||
| 32a7ed74e8 | |||
| 3913fce638 | |||
| 16f86b0770 | |||
| 2907083b73 | |||
| 1fa823d815 | |||
| 6e8e2112ba | |||
| 9560d10771 | |||
| e543818e3e | |||
| e0bb258b39 | |||
| d3ef0b9a4f | |||
| 86d623a0f4 | |||
| b964fa777c | |||
| cde017f791 | |||
| d1982a664b | |||
| 7e479d62dc | |||
| 6be32f3ba4 | |||
| 049a1ec8f6 | |||
| b3754b10c8 | |||
| 7441be730e | |||
| 38f9cb750a | |||
| 8a9aab57c0 | |||
| b61ec3a65a | |||
| 74c2ae627a | |||
| 74ca1e50f3 | |||
| 5fc929b829 | |||
| 3aaf895514 | |||
| 2057ccaeb5 | |||
| dc7b8f3ff2 | |||
| 2b7e9d826d | |||
| c57470e0d3 | |||
| 6b1379a992 | |||
| f1eb5d2106 | |||
| ad248ab76a | |||
| f4888c7940 | |||
| d02b12c9a1 | |||
| 2cf9d5ac4c | |||
| f3803fc071 | |||
| a3c6235f3a | |||
| 7501eefd87 | |||
| 2134116cbc | |||
| b86143de46 | |||
| 7c8045aab5 | |||
| c15bd0092d | |||
| d233d83811 | |||
| df0c375541 | |||
| 886b1b4ded | |||
| 48816135df | |||
| 4d0f698937 | |||
| fdbc79d2a8 | |||
| 1a89b0aa14 | |||
| 8e9b7cf259 | |||
| bf6643844b | |||
| e9c3ed1531 | |||
| 7dfcdc6da8 | |||
| 9ad7096851 | |||
| 4cdfb2537a | |||
| 9280e13697 | |||
| 21872edf83 | |||
| b7e021ffc6 | |||
| e69bb3aece | |||
| 06512a00e1 | |||
| bdfe294e61 | |||
| ddb9f370af | |||
| b0c0384401 | |||
| bf6e381ff2 | |||
| d5fcc77579 | |||
| b0097982af | |||
| 2e3a8a0fc0 | |||
| 357eed44a1 | |||
| 2ae70cd05c | |||
| d370ae1095 | |||
| 5c48ad9a79 | |||
| 621b5b4ec1 | |||
| 4dbc83ccbf | |||
| 398a64b5e0 | |||
| b926dbbbe9 | |||
| b244b33402 | |||
| f2e4b25615 | |||
| 29f2f1db2c | |||
| cec09e1c61 | |||
| 36a42116e8 | |||
| d9dcaf8ba1 | |||
| 984cf13afd | |||
| ac41bf6e86 | |||
| 5f21e3964e | |||
| 364cd86191 | |||
| b1449ca502 | |||
| 6110a0827c | |||
| 71b64139da | |||
| 3582ac91d7 | |||
| 30997bd9ef | |||
| cb673135d2 | |||
| 6ac1cf1a5f | |||
| 8f29a32a33 | |||
| ac3520791e | |||
| faa6e91ed2 | |||
| 86956b0be1 | |||
| fdc39982f3 | |||
| c37cfacb44 | |||
| 3af53a6598 | |||
| 19c500de27 | |||
| 855d538ea3 | |||
| 6b1ef16e38 | |||
| 1577da25cc | |||
| c44695eb37 | |||
| 63fdf67568 | |||
| 80cb7281ba | |||
| cefe5965be | |||
| 2a9f47ea2c | |||
| 85324f9a43 | |||
| 2e776ad155 | |||
| f6544f69ca | |||
| c61222403e | |||
| c487f24611 | |||
| 8dcd40c8f3 | |||
| 0ea2cb5a7a | |||
| 5a4a2f3ffd | |||
| 5293b328b7 | |||
| 2889aab226 | |||
| 7a1a25991f | |||
| 43f8e5e933 | |||
| f4940d9344 | |||
| 701cdff982 | |||
| 450c915284 | |||
| 892e437428 | |||
| 8905157c1e | |||
| 2eb57995dd | |||
| b64b88eb65 | |||
| 3da4b6411c | |||
| e115634812 | |||
| fc0f354df4 | |||
| ba5cbd5ca6 | |||
| 505b060637 | |||
| 12b9bd0a6d | |||
| e8715ffb96 | |||
| 5d34b137a3 | |||
| ad352a6703 | |||
| 7d69d18473 | |||
| 668abe4b0a | |||
| 5dcccfda3b | |||
| 56b271850a | |||
| d338e94267 | |||
| 42abfe3c7d | |||
| 6ef6540378 | |||
| 9a9b8e0a7b | |||
| 5ad86f559f | |||
| a8b0e19a33 | |||
| 2b61fbb8df | |||
| dea6ce164c | |||
| 9ebb705e75 | |||
| 010dfa52e3 | |||
| db9d9d1f77 | |||
| 6f342bf119 | |||
| 48765e82e0 | |||
| f141cd1dea | |||
| 6258856d2b | |||
| c93ea188f7 | |||
| 329eb419f5 | |||
| e83c42ca26 | |||
| f9eae4153f | |||
| 7b41f4783f | |||
| 7227cfc68a | |||
| 6b87a43162 | |||
| a4c6bf90aa | |||
| a31e894411 | |||
| 91e78fd746 | |||
| 3abe5de533 | |||
| dfa3c7311f | |||
| 2c5b8577aa | |||
| 4e804a9d4d | |||
| 0ca8c5f56f | |||
| 912798e5cb | |||
| 5bcdd7fdf0 | |||
| 78ffc4c192 | |||
| 966b76182f | |||
| b7101494f2 | |||
| be467b3dc4 | |||
| ee70d96c75 | |||
| 8fbd380879 | |||
| 7746518c0a | |||
| c8a98e27e0 | |||
| 3df902af23 | |||
| 45542e26cb | |||
| 49f73b118c | |||
| 6e3dcfddb0 | |||
| 09088045ac | |||
| e466232757 | |||
| 2ccd6654c1 | |||
| 7d7a6b881e | |||
| 9661227d00 | |||
| 5855c67d4d | |||
| 3edfe2b76f | |||
| f36bfe24f6 | |||
| 9da4b3a45a | |||
| 95524a6af4 | |||
| d4b61541b5 | |||
| 143c378ba6 | |||
| dfac93aebb | |||
| b6daca37d5 | |||
| 4937619ea0 | |||
| 6d34532301 | |||
| fb733483c6 | |||
| 2670bb149d | |||
| d49eda63f8 | |||
| 08e0fee141 | |||
| d204b9b408 | |||
| c53e0228c5 | |||
| 31cffd8412 | |||
| 0f71fe28a2 | |||
| f00a29d3df | |||
| e111389d6c | |||
| 7079341416 | |||
| 7fdbfc0c1a | |||
| e1dff1c931 | |||
| 90b2536a99 | |||
| 97f54318e3 | |||
| f1481f0deb | |||
| b1a9cde690 | |||
| 1ed2a0a0f1 | |||
| 759645cab6 | |||
| 3203251539 | |||
| b84b94b4db | |||
| 3dd77edd16 | |||
| a24165083f | |||
| 8878482ca1 | |||
| 19c7bbf97d | |||
| 23f15947d3 | |||
| 152129bf70 | |||
| 20ac32c34c | |||
| 707b40e8c2 | |||
| 0d1d9f4634 | |||
| 5a64ca48ad | |||
| f4ddf18124 | |||
| 657cf68e55 | |||
| f0013a4d65 | |||
| 83fe0249b3 | |||
| 3701199cfa | |||
| 4b56bfac05 | |||
| 613a997694 | |||
| e690e8910c | |||
| 34b9a8d21f | |||
| 0106ed3d91 | |||
| f8342e4b04 | |||
| 8a74b192b0 | |||
| d0ac539d09 | |||
| 0be4856144 | |||
| 7503b85f6a | |||
| 4a9abf20b3 | |||
| 2836bb5c41 | |||
| e2925ba01b | |||
| f2724b745b | |||
| 712d20079a | |||
| 99a5409b39 | |||
| 72fe06aa00 | |||
| 8081a3f9ff | |||
| f218f9b5a2 | |||
| 4e38751187 | |||
| e36e3bcf96 | |||
| 18503e5eb8 | |||
| 110c5dcf10 | |||
| 37f5a462e4 | |||
| a1fb756831 | |||
| 5a456eb295 | |||
| ad639ffb61 | |||
| 2ae686c366 | |||
| 641c9fba9c | |||
| 8473d8120f | |||
| 954db4e246 | |||
| 4f43bc5ec7 | |||
| 0bcc79baab | |||
| e7d34a5ab1 | |||
| 33f81fd490 | |||
| a1c156cec1 | |||
| 3d62482fe9 | |||
| 470c9ffed0 | |||
| 49c70046e4 | |||
| ff1b01bd10 | |||
| 5bcb07dc7f | |||
| 35475a260f | |||
| 3d377ec0f3 | |||
| bca33372c2 | |||
| 96696b33c4 | |||
| 5772941057 | |||
| d676ad814b | |||
| 5f9fdb0b15 | |||
| 0f44fd0064 | |||
| ceba60831c | |||
| fd90df5d54 | |||
| 3fe2c29204 | |||
| 55d4aaeef5 | |||
| 71d3b77668 | |||
| 0d3ece98c1 | |||
| 3dc83e4075 | |||
| b57ac04728 | |||
| 3d952d3c0f | |||
| 0897423e69 | |||
| b994ddf894 | |||
| c322cc5621 | |||
| d943283f80 | |||
| 995707a43e | |||
| 107b5e6ab9 | |||
| 2e0fdf7eb4 | |||
| 14ecf54d8a | |||
| c6bdeae570 | |||
| 2d539a9b8f | |||
| 8e1f05082e | |||
| 170d86be9a | |||
| d810b2d073 | |||
| e948bab4d9 | |||
| 7bed1417b9 | |||
| f7eea71b0b | |||
| a0eee06c16 | |||
| b7c013c1e8 | |||
| 1ee2eaf5e9 | |||
| fe55012007 | |||
| 42eb31e7e1 | |||
| 83423adc05 | |||
| b019f17590 | |||
| e58ba2e044 | |||
| 79ca8e968c | |||
| 5a095c3771 | |||
| 65094532eb | |||
| 13caa6691c | |||
| bcd1770a46 | |||
| aa96d87502 | |||
| d20be2aaf8 | |||
| d2ded394f6 | |||
| 2b8f458a38 | |||
| e3a7ec6aed | |||
| 93f9fd7206 | |||
| 28915fdce0 | |||
| 497455d281 | |||
| c758cbda5e | |||
| 4655133843 | |||
| 672a97cb34 | |||
| 0f8cc79c00 | |||
| e2b6865938 | |||
| bf0bc6468a | |||
| 526bf15c3c | |||
| bdfb0e3e25 | |||
| 2d6ebf16d8 | |||
| 13c62043eb | |||
| 39d60cd91d | |||
| aaf79c5202 | |||
| 884c790009 | |||
| 5e5dbf5984 | |||
| 0794cfec9e | |||
| a878374d28 | |||
| 120861bf55 | |||
| b7514e1e04 | |||
| da390e3959 | |||
| 3062759ca8 | |||
| cb4b417f76 | |||
| ef951094b3 | |||
| b14aefa1d3 | |||
| aa7c11a873 | |||
| b871699103 | |||
| 8b946ec36d | |||
| da73e1eda9 | |||
| cd8716400b | |||
| 854ab0b151 | |||
| c1c98e16d3 | |||
| 1ee99268f1 | |||
| 403ed3abaf | |||
| de2ae678a9 | |||
| 45c92568a1 | |||
| 2f455409e2 | |||
| 55bdde560a | |||
| 4e249125eb | |||
| 1f0ba0198b | |||
| 145ccc77d6 | |||
| 1cb0908961 | |||
| 1db7fbad66 | |||
| 7d79b35f93 | |||
| 2f331b7a8b | |||
| d96d5335b4 | |||
| 4c2150fb3d | |||
| 2751b3515b | |||
| 76b36a81ca | |||
| 3eb244898f | |||
| 7aacf9836c | |||
| 24eeb67275 | |||
| bf86730a62 | |||
| 98494420c5 | |||
| 7717ff01a1 | |||
| 5c3576c7c6 | |||
| d6576ed2f1 | |||
| 9a61c8f8dd | |||
| d192ec8fae | |||
| fe913577f6 | |||
| 312d00cc33 | |||
| c3ac504c10 | |||
| 5d94f0eea6 | |||
| 97734fd895 | |||
| 596e1ce135 | |||
| e1c58b4584 | |||
| f5d470c531 | |||
| a87277c6e8 | |||
| 6700ecaf43 | |||
| ad8a11bb49 | |||
| ce2051ed39 | |||
| d16989ce55 | |||
| a26e1c0f41 | |||
| 510267f6e9 | |||
| 8e6a5e19c2 | |||
| 21244ab832 | |||
| 7a64f1634f | |||
| 2d8268d3d0 | |||
| f6b96e4984 | |||
| 7fd972d669 | |||
| 42190df874 | |||
| 19673e3b1c | |||
| b6b334dd16 | |||
| a8443abe80 | |||
| 49b630c2d4 | |||
| cd56cae032 | |||
| 6c74aa0289 | |||
| 8ce147dcbd | |||
| 7f51c8dba4 | |||
| 7c2ba681e9 | |||
| 1c459e6ee6 | |||
| f6a077e102 | |||
| b797862a91 | |||
| abc7327116 | |||
| 7c58a8247c | |||
| 263150e599 | |||
| 7a177d6ac0 | |||
| d5e5c08b87 | |||
| c485bc975a | |||
| 2dfdaca3eb | |||
| 56f11f94d8 | |||
| ccbe691cc8 | |||
| f8b53c1cf7 | |||
| c920354423 | |||
| 1ab8cc4c0f | |||
| 3aa62a821a | |||
| ecf76830a5 | |||
| ce6ca0cf9d | |||
| 202a438044 | |||
| d7ffd48c67 | |||
| 7440e7f789 | |||
| f813bbdf86 | |||
| 2656bfbcac | |||
| dc95efea1a | |||
| 81e7e4dd81 | |||
| 57a2b65488 | |||
| b23e47c478 | |||
| ff4ca3098b | |||
| b6f8363023 | |||
| 9c07cf60a6 | |||
| 36324af017 | |||
| 31392ce1aa | |||
| 6cf039eecc | |||
| 79ab9800c0 | |||
| 05373cbb6b | |||
| 1b009da4d0 | |||
| b39b6b7635 | |||
| c2d3713f40 | |||
| c4345c809e | |||
| c761934868 | |||
| 77c4a09a9b | |||
| 58326b8fff | |||
| ee5d4b9e73 | |||
| e667e6dbd9 | |||
| ec288246d0 | |||
| 71c332803a | |||
| 5e30830cb9 | |||
| 57054f7451 | |||
| 1c6c085127 | |||
| ff4d25d454 | |||
| 85cb09ae6d | |||
| 854a5aa3c3 | |||
| bde33a1d6a | |||
| 8d98d8752b | |||
| cebeb4ea5f | |||
| a3a27a9a6c | |||
| 973c72bdf0 | |||
| 7bdd180c30 | |||
| 19d2fe8738 | |||
| 3d5a2d26d1 | |||
| 4e37a14bf8 | |||
| 91500344d4 | |||
| d8fe1a17cc | |||
| 9945ce7583 | |||
| 54d36f89ea | |||
| 193cf30780 | |||
| ab8c09fcb9 | |||
| 1db53ba155 | |||
| b41bb5c595 | |||
| c7676755ab | |||
| 4f88b3865f | |||
| 089d2db104 | |||
| fefb6ad4c4 | |||
| 05b795bc14 | |||
| ff3f5067c8 | |||
| 0c54f60e17 | |||
| 82b33708ba | |||
| 5b8289c05a | |||
| ea5cabb27f | |||
| a6b9fb285c | |||
| 4041d06e95 | |||
| 13cd5aa4ce | |||
| 00b504ebc5 | |||
| afb83a6cb9 | |||
| f5b03fb2e8 | |||
| b8d3aa2a68 | |||
| 52f154ec02 | |||
| e4d0693eb9 | |||
| 4a42c93897 | |||
| 8b438dea76 | |||
| 12977a50bc | |||
| 33f84624ec | |||
| f252480bee | |||
| c9df887c4c | |||
| 03edf7f4a8 | |||
| a98a719546 | |||
| a97483b928 | |||
| 9955886ef5 | |||
| 3646a7143e | |||
| 13f40e4333 | |||
| 6249660e1f | |||
| 3eb2d3c4b3 | |||
| 8f1fc75fdf | |||
| d3c37344f0 | |||
| 5e8b6a9e55 | |||
| bbd0eedb5f | |||
| ad51b34438 | |||
| 0d4b753409 | |||
| 6f5727cbdb | |||
| 10e88d07af | |||
| 3f1e4a703a | |||
| bc9eca70d0 | |||
| 69b882a14b | |||
| 6984e6a4f2 | |||
| fd0cab2ab8 | |||
| 93216374ef | |||
| 8ba710637a | |||
| 937c3484cf | |||
| 59db6cf788 | |||
| f41b3e8295 | |||
| fe439890e8 | |||
| e29f762116 | |||
| c8abaf32ee | |||
| c0a9f638ce | |||
| 4a90ae5b0f | |||
| 7ccd62ba98 | |||
| 2e1ef850e3 | |||
| dbba786a35 | |||
| d0d4be9e35 | |||
| 2d69c7a5ca | |||
| 24a38922bd | |||
| 1e553df5b6 | |||
| 0f37f774f1 | |||
| 34c07ea148 | |||
| 70fca4483e | |||
| b2b017accb | |||
| a97160cf57 | |||
| 1d42f5b7b1 | |||
| 70ac0509df | |||
| f1678399af | |||
| bae1f8ca82 | |||
| 790c33d6a7 | |||
| a9f5da7799 | |||
| 6a59e6db39 | |||
| 76a44cff09 | |||
| e36dce52ba | |||
| c31ace5fc8 | |||
| c494b3db58 | |||
| bf0c3c188e | |||
| 0f9f3eba72 | |||
| 0960f885d5 | |||
| 33b28a514e | |||
| 2497d663b7 | |||
| 887f1dc07c | |||
| 0d033679d4 | |||
| 9abce00f24 | |||
| f3649e4ae0 | |||
| 6cf0342322 | |||
| 3252ad1f4b | |||
| 741a10f5a8 | |||
| c39dd284d2 | |||
| 4e5c97f3a3 | |||
| e10fc0f93b | |||
| 8207ebe381 | |||
| 6491f6c10a | |||
| cfd4bacc2c | |||
| 09be9bae04 | |||
| c01a8c4629 | |||
| cdb0229cf2 | |||
| ddf302fcc2 | |||
| ca9e9584ba | |||
| 0d34053870 | |||
| 66533ace80 | |||
| ea599a66b7 | |||
| 1cc3f680e8 | |||
| f7665a2743 | |||
| dc9faddf22 | |||
| e64c5b34df | |||
| 57492c1a94 | |||
| df8fbca007 | |||
| 72fb9c7c96 | |||
| ce0f16f328 | |||
| a477d70f32 | |||
| f3476de893 | |||
| dea525b2b7 | |||
| d55c9565ab | |||
| 00a4185cf1 | |||
| ea28a3f98e | |||
| c8facc99a7 | |||
| d7ec41f4c6 | |||
| 9f2063846b | |||
| c05c541216 | |||
| 34e54b35e8 | |||
| f12009fc61 | |||
| 5854090dc7 | |||
| 7e28fdd45a | |||
| daeaf5e98b | |||
| 4bffd7a85d | |||
| 7615fabc80 | |||
| be0acc575f | |||
| 9d558b010d | |||
| 32773fb023 | |||
| 64441d2b64 | |||
| 07758b7af8 | |||
| 92ce66be64 | |||
| 15befe998e | |||
| b50e0d610f | |||
| f99dee1917 | |||
| 6327d174d2 | |||
| c2b9b22f67 | |||
| 311e126ac4 | |||
| c037169e1a | |||
| 9bb861accc | |||
| ecd5b239a4 | |||
| a600ef6cbb | |||
| b90da4a802 | |||
| c50ba694a5 | |||
| 8f7b7ca7b3 | |||
| adfc7f4d5d | |||
| 9e18dc1401 | |||
| cf76763ab7 | |||
| fb7ef4cf63 | |||
| 04a0909105 | |||
| 613f154d47 | |||
| 978944fab2 | |||
| 705e69aefd | |||
| e58081f6dc | |||
| 4ac8a45a34 | |||
| 6b5b968b97 | |||
| 2ab82ad653 | |||
| 86df284ad4 | |||
| 3521c87e17 | |||
| 32533f7325 | |||
| 0e19bdf50a | |||
| f72b0353d4 | |||
| 0676b4f4ca | |||
| 929982357a | |||
| 5190a5d7f8 | |||
| 7775aa83df | |||
| fc1604f2c8 | |||
| 5b97fbc292 | |||
| 4f5a2dabe9 | |||
| e0227618bb | |||
| ee9a5a2c77 | |||
| 6fffc738f7 | |||
| dc611fc828 | |||
| 12ee29579d | |||
| a897843f6c | |||
| 80de85f217 | |||
| 242e91a9fd | |||
| ca80237191 | |||
| b95ef6de04 | |||
| 76e7322262 | |||
| 3c42138e45 | |||
| 1b0b38a519 | |||
| 9119a42b7d | |||
| 8af4b37d14 | |||
| 31c5b5bfa1 | |||
| b6c6bfbe7f | |||
| 6e074d7165 | |||
| 0489069419 | |||
| 597eb5a3fd | |||
| 3fe259a79e | |||
| 6ef17a0f0e | |||
| 47a8c3fc67 | |||
| d49d0e90a8 | |||
| 77bd45b1fa | |||
| 622dff50df | |||
| 41f6a051ef | |||
| d05619095c | |||
| 2f8492d720 | |||
| 7911f491f6 | |||
| d84a57441b | |||
| b8c754d230 | |||
| 338a94e577 | |||
| 2e14c340a8 | |||
| 35522d3ee0 | |||
| 8c139940e7 | |||
| 7b5f73f6c2 | |||
| e7a3487df4 | |||
| c243895fc0 | |||
| 451d0f2fc5 | |||
| c75b332240 | |||
| 899248acbf | |||
| cae6b121b2 | |||
| 5f6ee3da9c | |||
| bfcdd51b4a | |||
| 10b736d407 | |||
| 0b61e6defb | |||
| 28f529100d | |||
| 6466ce0b51 | |||
| 03baef8b28 | |||
| f1435d53d4 | |||
| 20b0c0a6d8 | |||
| a1b1df84a0 | |||
| 408ebd0a0a | |||
| e9c4696544 | |||
| ea64f2e46e | |||
| 94a3a9baf9 | |||
| da27ae4de6 | |||
| ed326e2c87 | |||
| bea4c6e29b | |||
| 61df9479e5 | |||
| e3ab7b5d2e | |||
| 679b73098e | |||
| cba643fc51 | |||
| 1c8edf0298 | |||
| 07b9a7d60e | |||
| 9c8980e6a1 | |||
| 60127d86e0 | |||
| 0c3c738614 | |||
| c8bacbcb00 | |||
| b070bb5e49 | |||
| e518120104 | |||
| 84f1ef6d2d | |||
| 77bf2b5e33 | |||
| 8229aa6b3c | |||
| fc08f62d6a | |||
| 1254520438 | |||
| 7941771d61 | |||
| 4f1c6e1ebf | |||
| 13ff1e7fb1 | |||
| 25b0b66e52 | |||
| da835e88b8 | |||
| b6c229e2bb | |||
| 19a45e028a | |||
| 435b7450d4 | |||
| a41a0f3a06 | |||
| 814926ef31 | |||
| f6f5ecdc00 | |||
| 42b6b13943 | |||
| cfe4c26f99 | |||
| 3117611a55 | |||
| 1e491533fa | |||
| a119caaa1b | |||
| 96f8f85eef | |||
| 2add451d63 | |||
| 3effedb728 | |||
| b067e65731 | |||
| f3b179d451 | |||
| de5373413b | |||
| fedf533699 | |||
| 9cd673c71d | |||
| 85a834cf62 | |||
| 5167c970af | |||
| bf7a65010c | |||
| 461ac96a2c | |||
| 5eb10fd0b2 | |||
| e2e9959389 | |||
| d8969c71fc | |||
| ab76814aa6 | |||
| 1a18cd2196 | |||
| e4a00980f8 | |||
| af94e6a40e | |||
| ee73a53497 | |||
| 6bdf1ba244 | |||
| d47754acac | |||
| cee94e9fcb | |||
| 3ae9930979 | |||
| 2effcfa195 | |||
| 8c9080f11f | |||
| ef05493c83 | |||
| 7a0a598649 | |||
| cafd236a18 | |||
| e0054c7dd0 | |||
| 3414e6628a | |||
| 08ce2c98e0 | |||
| 6d79a322e2 | |||
| 9e70680044 | |||
| 7de8c91301 | |||
| c333a7f9fc | |||
| bc36a06a2d | |||
| e62ac22f0b | |||
| 1092c972c9 | |||
| 7e5520f974 | |||
| 2b01bdbc25 | |||
| 64a3be7d3e | |||
| c0e03c3640 | |||
| ed8c0f9ecd | |||
| 2bfc59c461 | |||
| 727e36e6a6 | |||
| 09bddd8df4 | |||
| f089adc160 | |||
| 97b68ea05e | |||
| 972ac220f5 | |||
| 5d98f3d0f0 | |||
| 51cd1cd2af | |||
| 7e940e6e45 | |||
| 7aa7d8935c | |||
| 2f4d286a51 | |||
| 1bc5d87c5d | |||
| c2d2be021a | |||
| 6b32d6bf09 | |||
| c18f57f62b | |||
| e657f75a17 | |||
| d060d3a0e5 | |||
| 3c8c360f8c | |||
| 0af2c732ab | |||
| 68fe365f5b | |||
| 91bbd5fcb2 | |||
| ac6b6bca48 | |||
| b6e3f2303f | |||
| da370a6a1a | |||
| 4aa74e5feb | |||
| 13322fe858 | |||
| 0645700b33 | |||
| d89aadc56c | |||
| 21a24d6cd7 | |||
| 9c4c3a754a | |||
| 5f5f8ef1e4 | |||
| 958d206bb6 | |||
| 8fa93cc55b | |||
| 79cf0c4bfb | |||
| 81aefde94e | |||
| 96602df8a8 | |||
| c0b72d97b3 | |||
| ddee1b686a | |||
| 2231586033 | |||
| 13063abce5 | |||
| 570decf00e | |||
| bf5ef9824d | |||
| 01dcd36c41 | |||
| b2f2fdc2f3 | |||
| f2af10c746 | |||
| 3bf664ad31 | |||
| 67ab88b064 | |||
| 67f1f65174 | |||
| b1dff42434 | |||
| 57cc6d4bac | |||
| e416cafd49 | |||
| 0aa79ce360 | |||
| 0a1c9ad4c5 | |||
| dd85b16166 | |||
| 76127b6e42 | |||
| 03a597983e | |||
| 33f701dd09 | |||
| 3db4654b44 | |||
| a7546e298e | |||
| 8a0592a35d | |||
| 98cce956f9 | |||
| a34785fa0d | |||
| 14ccdbc7b6 | |||
| 5b5b46ea1c | |||
| e3f534a148 | |||
| 1bcd5b0003 | |||
| 0d1cfba823 | |||
| e986b70981 | |||
| 9b7b485c33 | |||
| c680fa7418 | |||
| 9772c01161 | |||
| 6071f9a08b | |||
| ad2256b13c | |||
| dad0d48c9c | |||
| e03a8732a6 | |||
| 7da307c696 | |||
| 82438a513b | |||
| b5205e58aa | |||
| b907cee691 | |||
| da6e8e8041 | |||
| 3fd4495b2f | |||
| 04607dc9f3 | |||
| ece4116329 | |||
| 74abdd6973 | |||
| a316d3fa46 | |||
| 70ce6b4ae7 | |||
| ade302f0a0 | |||
| 147885fec4 | |||
| 65aaf27380 | |||
| b1588929cc | |||
| 094fa38360 | |||
| 71d19820ac | |||
| a0dc86ecbc | |||
| 982685d3a0 | |||
| dadb4486ee | |||
| d14c1dec59 | |||
| 21d6d7bc21 | |||
| ff0228e752 | |||
| b00bc15c3e | |||
| 50c4cbe06c | |||
| 573e10665c | |||
| d0acb81f2e | |||
| e7b20d2877 | |||
| 588ad6e69f | |||
| 98462fbcc3 | |||
| a93331dd96 | |||
| e174af2286 | |||
| 9decbe0cbd | |||
| 021817f2b4 | |||
| 13ff69efbf | |||
| 8fda9113b8 | |||
| b881bcfee3 | |||
| 1c606980ec | |||
| 0d6e58d9fd | |||
| 95e477902e | |||
| cc32bfb96f | |||
| 7c2f11f8e1 | |||
| d08dcb7465 | |||
| 2d1d6ccd75 | |||
| 7f380028cc | |||
| 827f77729f | |||
| 6c81de37f5 | |||
| 86a8a0429a | |||
| 4b00548138 | |||
| 8bb9473443 | |||
| da7a5bf269 | |||
| 7434e116a7 | |||
| 8f51dc6082 | |||
| 79deac97dd | |||
| 9debeadee7 | |||
| cae72eec2f | |||
| e58370b4ff | |||
| e92f7d86c1 | |||
| 93a33ba15f | |||
| ad353c8e3d | |||
| 09717ffca4 | |||
| ce4b840299 | |||
| 5a8df0ebe4 | |||
| 6029d1cfd0 | |||
| 3fe46a1769 | |||
| 5490bcfe95 | |||
| 078c562b6c | |||
| 88612a8be4 | |||
| 37a6903831 | |||
| 8017d9e684 | |||
| 609ae6cb4e | |||
| 603f785739 | |||
| 992f9ccf21 | |||
| e250fb44f6 | |||
| 9767d86d97 | |||
| 7687c99708 | |||
| 81cc773013 | |||
| cdb887e880 | |||
| 041fee64df | |||
| e3dd1f276e | |||
| 0769ecd70d | |||
| 2be69b3eb9 | |||
| bc601e34d2 | |||
| 79e39d9d43 | |||
| 6bc57bd398 | |||
| 1bca2df642 | |||
| 59cbe3d483 | |||
| 21f2522695 | |||
| 3720b0be58 | |||
| 413b45a62e | |||
| 7b8e3d01de | |||
| b4a3c6f460 | |||
| 1d4845d6b8 | |||
| c26acdba15 | |||
| 3f42a56bae | |||
| 144a0c1791 | |||
| cc2b1a1ef1 | |||
| 84dd473a5d | |||
| f014802eb6 | |||
| 68eb654e7a | |||
| 3a507b4e39 | |||
| 0273ec59d7 | |||
| 9090d87725 | |||
| 8ccde2e5a1 | |||
| 31211a607f | |||
| 56ab93d296 | |||
| 1d8855da27 | |||
| df5a7538b1 | |||
| 0cedaf7ad6 | |||
| b4795f414d | |||
| 2c9d209eef | |||
| a81c86a90e | |||
| bf0f90ff03 | |||
| 7c6f1ef227 | |||
| 99985bb1b2 | |||
| 8c5aa5086d | |||
| b1232d8061 | |||
| 2f6b81d8c1 | |||
| e1b39bbbfb | |||
| 6b7cecb9d3 | |||
| 79dcf7cbe8 | |||
| d4702754b7 | |||
| 98d90f26d7 | |||
| b97ceb6442 | |||
| c18c645b92 | |||
| 15cb6d7d1b | |||
| 2f5d98a0cd | |||
| 2216c987a0 | |||
| 86d4d21250 | |||
| 3eb2355182 | |||
| 9440395330 | |||
| 034f2c3779 | |||
| e93f5b0971 | |||
| 8c6f3e910b | |||
| 78bd2c0736 | |||
| 4e6ce91dd0 | |||
| 850d69738b | |||
| 9c62f83e74 | |||
| 99fdce0b4d | |||
| 06b6418044 | |||
| 57819d1dd9 | |||
| 80f3376894 | |||
| 94071cc6e8 | |||
| 038550a9df | |||
| 9ca8c691ac | |||
| a4881436d2 | |||
| 70190b3aa2 | |||
| 8ae166a2c3 | |||
| 7d0c6d2425 | |||
| 5995e5521f | |||
| 59c83ab942 | |||
| 0a552a47cb | |||
| 3b5cf359e7 | |||
| 239453bead | |||
| bea92e8842 | |||
| ddab816ed7 | |||
| 007ddb9a5a | |||
| 6b1a4bfeb7 | |||
| 6ca8d5e0d9 | |||
| 6f3dee13a8 | |||
| 7f14796ba4 | |||
| cfb4a9d254 | |||
| 621c1523c0 | |||
| b4d62e4670 | |||
| 3922d1bb63 | |||
| 9b9a1d21a6 | |||
| 033a611f71 | |||
| 3aa91346ea | |||
| a7c0ddb5b3 | |||
| de0366105c | |||
| 3508ceaa58 | |||
| 29660f9c4d | |||
| 52b42b4e48 | |||
| c88126e1d2 | |||
| e6a6fe92d7 | |||
| 0c7c7cc6ad | |||
| fb93c8cb86 | |||
| 8f0126a13a | |||
| 0f080552fa | |||
| f8a6ea40a1 | |||
| 1a067034c1 | |||
| bd10a8b5aa | |||
| d603e75d03 | |||
| a422b40041 | |||
| 44f61e5878 | |||
| 27c4e90374 | |||
| 0221f1a9bd | |||
| 6b21eeccab | |||
| bf1f24ab04 | |||
| 34b69e67ee | |||
| 64994d76dd | |||
| 10049f8325 | |||
| 654fed166a | |||
| 1bd3b029fa | |||
| 3305caf40c | |||
| 85d2657ac1 | |||
| 8fb85cbb8d | |||
| da455124d2 | |||
| ef4d33ce89 | |||
| 7eefe62efe | |||
| 981f1e2acb | |||
| 73c0d85ae6 | |||
| d495cbd7e6 | |||
| ccc3d1c83d | |||
| 38d8d052d1 | |||
| 2e26534659 | |||
| d1a6e948e3 | |||
| 81897a6469 | |||
| 8f8ea09ce8 | |||
| ced2139eea | |||
| 9b398ba0c9 | |||
| 556adc1de1 | |||
| 3f060a70d1 | |||
| d6322718f3 | |||
| 0a8037243b | |||
| 94ef1ac391 | |||
| 53f278312f | |||
| 549b93e629 | |||
| c2e7221bf9 | |||
| a0ceefc91a | |||
| 37d58e84e3 | |||
| ec6219fe13 | |||
| 05f7c37f54 | |||
| e68f0c341e | |||
| f47f0f8d16 | |||
| ed369d6374 | |||
| b6b54610c6 | |||
| 1d03bbe213 | |||
| 32ab636fe8 | |||
| 8e5ffbbe6c | |||
| e7f495c094 | |||
| 1e07edc1ad | |||
| 2f09079d3f | |||
| a1bdd82bd5 | |||
| 45b6340a98 | |||
| 22e6daac6c | |||
| 9ea735c975 | |||
| 31f3a10d33 | |||
| d9f49f2b44 | |||
| 73c269398a | |||
| 7a4930f1a1 | |||
| d5971171da | |||
| 035396e89f | |||
| c0faf59a86 | |||
| a822b27efc | |||
| f1e716d897 | |||
| 612d68eecd | |||
| aefea862c2 | |||
| f8968ab022 | |||
| 8f86c2464e | |||
| cd57bf5000 | |||
| a7125259d8 | |||
| 3a163b5449 | |||
| ff31c73970 | |||
| 2e11fd8a86 | |||
| 09c546f63a | |||
| 8683332b2c | |||
| 5be71a0e90 | |||
| 27f5496a65 | |||
| 918b3da91d | |||
| 61516be1db | |||
| 7c968fd38d | |||
| d77453b7ad | |||
| cf9930fe20 | |||
| e30a99d2fc | |||
| 4a066e4b18 | |||
| 0fccd93e29 | |||
| 6932a2d571 | |||
| f387994422 | |||
| 958b1d468f | |||
| f5292fd9f7 | |||
| ada08d9459 | |||
| 9a284b4106 | |||
| 98083078a3 | |||
| b8d96be8f7 | |||
| 68edec9f97 | |||
| 39bafd7b10 | |||
| c788780792 | |||
| 0acb4ee3e6 | |||
| 893ebc5adb | |||
| 7158700502 | |||
| 1eac47a275 | |||
| c6f0175c79 | |||
| e1416d0a3e | |||
| 6031b66f99 | |||
| 808f1f939f | |||
| d863f17673 | |||
| 24c08646f4 | |||
| 6604abe600 | |||
| 39aed02e32 | |||
| 6b44f3b887 | |||
| cd88cb4a30 | |||
| 32dc45b7bd | |||
| 275b03e76b | |||
| 995ef1efdb | |||
| 8cb85937c4 | |||
| e615ac67c2 | |||
| 880d778ab6 | |||
| a8cd8cdd0b | |||
| 401df0f2fb | |||
| 531f6804ad | |||
| d5230a874b | |||
| 030fd55d02 | |||
| 626bb48013 | |||
| e64f82ed03 | |||
| c8c71d0ad1 | |||
| 4e759b4444 | |||
| 9f199eaa23 | |||
| 2fed2fbd9e | |||
| 29d63e378b | |||
| 8a1a475c58 | |||
| 08230efb44 | |||
| 2aee3add16 | |||
| fa3d93ddbc | |||
| f6b8d3957d | |||
| 992cc0b077 | |||
| 2f92b12205 | |||
| 2e80a82554 | |||
| 5622afdafa | |||
| 63d56953af | |||
| 51d2e2564e | |||
| 2665090568 | |||
| d70fcb8c25 | |||
| ac0a2fe6c9 | |||
| 280b1971b6 | |||
| 6c09b89d0c | |||
| 8f982c8b27 | |||
| a61e876300 | |||
| 684e40464f | |||
| 2507fd78e3 | |||
| 21f1fe8185 | |||
| aeea8e05ad | |||
| abc556950b | |||
| 11c9955902 | |||
| 9cb361f35e | |||
| a8f75b7cea | |||
| c3477b2624 | |||
| a5dcc9dab0 | |||
| 6ebc2e72ff | |||
| 1f111edec8 | |||
| d2a6ad8c72 | |||
| 8591c1f180 | |||
| 087962c16e | |||
| 4471e056f4 | |||
| b56a5ead66 | |||
| e3befdba7f | |||
| 50e8df5e12 | |||
| 0cf8de5222 | |||
| b6a6f530c0 | |||
| 03245c80ff | |||
| 2775ae2f2e | |||
| 8557a30592 | |||
| fd530b87f6 | |||
| 674d635024 | |||
| f304e56818 | |||
| 5a2bf64a65 | |||
| f1b78931d1 | |||
| 3d7b6c64b5 | |||
| 597d93537d | |||
| 3a909c8747 | |||
| ad38ecf6d8 | |||
| dac1dc5837 | |||
| c0aaf908c0 | |||
| b1d782285c | |||
| b0620a46ff | |||
| 340c98d89a | |||
| 78241de393 | |||
| 17ba6c9916 | |||
| dbf7c9d6aa | |||
| 983ad956e0 | |||
| 45273ea6a5 | |||
| 9b82dcde10 | |||
| b496bc3fa2 | |||
| f8abb9633a | |||
| 76c37f7805 | |||
| 7d441864ec | |||
| ccd895a356 | |||
| 8ecdee5a93 | |||
| 0618d01f86 | |||
| 70c39ad5ea | |||
| 96fc0fa3c2 | |||
| c101aec06c | |||
| 5867994b8c | |||
| bd79d02049 | |||
| 0ea847a64e | |||
| 965e25c989 | |||
| a3ffd4a7c9 | |||
| 41b9b8d841 | |||
| 26a47d33c1 | |||
| 1154b5729a | |||
| fd1aec2998 | |||
| 659b6fe8ba | |||
| ceef4d6521 | |||
| 86b077b9a1 | |||
| 28cdebe7a4 | |||
| d4087f64d9 | |||
| 4ec5a0eebd | |||
| f58a3fc3eb | |||
| 11562b3285 | |||
| 568fd1758d | |||
| f64b5ba3f8 | |||
| 395c744d6f | |||
| 155077cba0 | |||
| 4dcf34c264 | |||
| 4bf3b1bfc5 | |||
| 6bc99ac0c2 | |||
| 09e856562a | |||
| f6f19aaaaa | |||
| 5dd13dbfb3 | |||
| 9ae19a64d7 | |||
| bd13f2b1ad | |||
| d09bbba6c1 | |||
| 3f4d031c43 | |||
| 674b39243f | |||
| 099a893678 | |||
| cfd52c8f38 | |||
| a4372314c2 | |||
| e295541dae | |||
| 785a6def3b | |||
| 53bdec8aab | |||
| 5191897696 | |||
| 2ecfa0e08c | |||
| c001139465 | |||
| e3353a445a | |||
| ce779452ba | |||
| eb8b8295a1 | |||
| 94c9c61142 | |||
| 11e390bf42 | |||
| a8fdf19c91 | |||
| 08bca9a35f | |||
| 1db630d5c9 | |||
| bbad921022 | |||
| f64cf03e1d | |||
| 559122f67a | |||
| 431f2abfee | |||
| 5f622027cd | |||
| fa97494cc8 | |||
| f4d4975077 | |||
| f030480e44 | |||
| 435c21c155 | |||
| 7438d7a02f | |||
| 0e5930b8dc | |||
| eacca89d4e | |||
| 99e6bef4ef | |||
| 3d5314b5f5 | |||
| f0517463a5 | |||
| c9e0fb9730 | |||
| d86a4b0c2f | |||
| eced4266c2 | |||
| fc483e60bc | |||
| 910cd41c47 | |||
| b4e1d32e85 | |||
| ff66f79721 | |||
| 8b610a6d34 | |||
| 20e923ba0d | |||
| 4777eaf367 | |||
| a40422fada | |||
| b1912055a9 | |||
| e8714d79b2 | |||
| f8e2a917f9 | |||
| 140e8852e8 | |||
| 547e141166 | |||
| 3fd5635d7d | |||
| d9c49a6cde | |||
| 8ade57b9e3 | |||
| 147181530d | |||
| a4750fbdba | |||
| a33949a0a5 | |||
| 54f9626c12 | |||
| 4d57147c3d | |||
| 3d7abd9cbe | |||
| 5a81ca6ffe | |||
| b9188caf7d | |||
| df726c038f | |||
| 14e0e1afc2 | |||
| 2c1a8894cb | |||
| a49c76c69c | |||
| eb04f68351 | |||
| 77bd36d038 | |||
| 1b85f812af | |||
| daad24388c | |||
| 0cbd02d3cc | |||
| 3a13ddb4a3 | |||
| 7b272c85d5 | |||
| 5edc45349f | |||
| dfaa61b666 | |||
| 076e195cac | |||
| 71a8e56ae3 | |||
| ef79fea0b7 | |||
| ea33b5d134 | |||
| 5bab4d4360 | |||
| 10e24f93c4 | |||
| 00cebc3dfb | |||
| ee034e23bb | |||
| 1d02663275 | |||
| e594f1eda7 | |||
| 1bcb5f8b6f | |||
| 06f63fdc0d | |||
| 7efcf9ccff | |||
| 6649b4df3c | |||
| 71096f4d26 | |||
| 0f0161a5a2 | |||
| b99382b551 | |||
| 493f905598 | |||
| 4e6292b439 | |||
| 2f0a94bcfd | |||
| 618a51df13 | |||
| 18a5010436 | |||
| c8b893cb77 | |||
| a1252fcc0e | |||
| ef67d9ae12 | |||
| 3e638049ec | |||
| 7f59e8e058 | |||
| 7023460394 | |||
| 0dcf1b5cd2 | |||
| 7b2c5189b3 | |||
| d3fe62a646 | |||
| 1f17294cd3 | |||
| 3882a61065 | |||
| df72c4886f | |||
| 26c72f9860 | |||
| 55957bbab5 | |||
| ab843eb587 | |||
| 4438b8e017 | |||
| 5747836754 | |||
| ba5c383877 | |||
| b4f08db391 | |||
| 060acb3f25 | |||
| 8727de1a1b | |||
| 8cde8d1252 | |||
| 6bac25221a | |||
| 5bedbde746 | |||
| 2fdd33381c | |||
| 8d4b503e56 | |||
| 6c24cccf96 | |||
| 51fdfa7ac7 | |||
| 3dff89c240 | |||
| 4e07c94502 | |||
| 854dc0b353 | |||
| 373791d0b2 | |||
| fe3d612fe0 | |||
| ae0c97a77a | |||
| 788a3661a2 | |||
| 1e24f85fbc | |||
| 4601f5c51f | |||
| 55eafdf0ee | |||
| 63e04cfb60 | |||
| d0a3efab6a | |||
| 2b8680d2c4 | |||
| 31cd8f4e16 | |||
| b75b7dd5ac | |||
| 437a35feaa | |||
| f76af2d0c8 | |||
| efbf13685e | |||
| 08d533cb88 | |||
| ff6e457651 | |||
| 965c2ae89c | |||
| 78b078f41d | |||
| 491fa330f6 | |||
| 9ec148aec5 | |||
| 7598d0d49b | |||
| 6a8506d959 | |||
| 7fe53ef5a3 | |||
| 1743ed118d | |||
| 848b73f99f | |||
| ccc88ecf0a | |||
| c40cb50fe5 | |||
| 386d9f28d7 | |||
| 4350660626 | |||
| 1632522967 | |||
| 178154082f | |||
| d5dac9bdae | |||
| cf363355df | |||
| ca018bfba6 | |||
| 3c48fa3818 | |||
| 7bc588d8df | |||
| 6d1aece43a | |||
| 7e1dbc4cb7 | |||
| 2b09a34467 | |||
| 78ea3024b5 | |||
| cec1891586 | |||
| 6d8ce11934 | |||
| b83a73ab40 | |||
| caa0b7cdf6 | |||
| 46caec7d77 | |||
| 04234cecee | |||
| 84ff0c3227 | |||
| 35a3894a88 | |||
| bde5df043c | |||
| 8f70ddf4ef | |||
| cfc134b871 | |||
| 20c9360528 | |||
| 09b239ed28 | |||
| 294d58d2fe | |||
| 3e70155100 | |||
| ce379f7bb5 | |||
| f8e1ec8d2b | |||
| 24091f8bd8 | |||
| 4c3c18467c | |||
| 3f0e2b478b | |||
| ac2409627a | |||
| a07e4c5810 | |||
| 5a86d08271 | |||
| 4ac0a12a83 | |||
| 290c7566ff | |||
| 6ccc68b15c | |||
| 188bcafdec | |||
| 3a8739cd60 | |||
| 2bc986ecbc | |||
| 638accbec4 | |||
| d8fb4f4c38 | |||
| 3e55934381 | |||
| 40a89ac649 | |||
| d442f20bf8 | |||
| d36fc98c15 | |||
| 700c4717d6 | |||
| 1e73578ab6 | |||
| 971224a282 | |||
| acce19ce43 | |||
| 77021c5bbb | |||
| fe3873b28f | |||
| c1e9a6ac59 | |||
| c2425106ea | |||
| c8e7874534 | |||
| 601daa0e5d | |||
| d022cc48ad | |||
| 527a72860d | |||
| f0bb74a530 | |||
| b75f06d935 | |||
| e2d1d75955 | |||
| 80dc7b5e6a | |||
| 1f4d8e7c21 | |||
| 366c09f199 | |||
| d98f72c4e1 | |||
| e6417fe652 | |||
| f5d52cc9b2 | |||
| 62427c8287 | |||
| ab588fe872 | |||
| fe1385ab34 | |||
| d6f513be52 | |||
| d8fa4cef60 | |||
| 506f478ec7 | |||
| f2c420e289 | |||
| eae2a90463 | |||
| 4305d10264 | |||
| d5b38b01fc | |||
| c49dbd782d | |||
| c7bde21be7 | |||
| d5fdc0b47e | |||
| c3d97bd613 | |||
| 2960390f79 | |||
| f723f857e4 | |||
| d66936a640 | |||
| 3640e1e96c | |||
| ec1e809fc3 | |||
| 8868fa4687 | |||
| ebd75b4010 | |||
| 9bd3f498a7 | |||
| 659a014976 | |||
| 885574e1bf |
@@ -0,0 +1,179 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# Copyright 2017 - 2019 James E. King III
|
||||
# Copyright 2019 - 2021 Alexander Grund
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /bugfix\/.*/
|
||||
- /feature\/.*/
|
||||
- /fix\/.*/
|
||||
- /pr\/.*/
|
||||
|
||||
matrix:
|
||||
fast_finish: false
|
||||
# Adding MAYFAIL to any matrix job allows it to fail but the build stays green:
|
||||
allow_failures:
|
||||
- MAYFAIL: true
|
||||
|
||||
environment:
|
||||
global:
|
||||
B2_CI_VERSION: 1
|
||||
GIT_FETCH_JOBS: 4
|
||||
B2_ADDRESS_MODEL: 32,64
|
||||
B2_VARIANT: debug,release
|
||||
|
||||
matrix:
|
||||
- FLAVOR: Visual Studio 2015
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_TOOLSET: msvc-14.0
|
||||
|
||||
- FLAVOR: Visual Studio 2017, C++14
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: Visual Studio 2017, C++17
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: Visual Studio 2017, C++latest
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_CXXSTD: latest
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: cygwin (32-bit, C++11)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: cygwin (32-bit, C++14)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: cygwin (32-bit, C++1z)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: 32
|
||||
B2_CXXSTD: 1z
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: cygwin (64-bit, latest, C++11)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: cygwin (64-bit, latest, C++14)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: cygwin (64-bit, latest, C++1z)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: 64
|
||||
B2_CXXSTD: 1z
|
||||
B2_TOOLSET: gcc
|
||||
B2_FLAGS: "include=libs/unordered/test/unordered include=libs/unordered/test/exception"
|
||||
B2_VARIANT: release
|
||||
|
||||
- FLAVOR: mingw-w64, 32 bit, C++11
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
|
||||
- FLAVOR: mingw-w64, 32 bit, C++14
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
|
||||
- FLAVOR: mingw-w64, 32 bit, C++17
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
|
||||
- FLAVOR: mingw-w64, 32 bit, C++2a
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin;
|
||||
B2_CXXSTD: 2a
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 32
|
||||
|
||||
- FLAVOR: mingw-w64, 64 bit, C++11
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 64
|
||||
|
||||
- FLAVOR: mingw-w64, 64 bit, C++14
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
B2_CXXSTD: 14
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 64
|
||||
|
||||
- FLAVOR: mingw-w64, 64 bit, C++17
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 64
|
||||
|
||||
- FLAVOR: mingw-w64, 64 bit, C++2a
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;
|
||||
B2_CXXSTD: 2a
|
||||
B2_TOOLSET: gcc
|
||||
B2_ADDRESS_MODEL: 64
|
||||
|
||||
#- FLAVOR: CodeCov (VS 2019)
|
||||
# APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
# B2_CXXFLAGS: -permissive-
|
||||
# B2_CXXSTD: 14
|
||||
# B2_TOOLSET: msvc-14.2
|
||||
# COVERAGE: true
|
||||
|
||||
install:
|
||||
- git clone --depth 1 https://github.com/boostorg/boost-ci.git C:\boost-ci-cloned
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
- if NOT "%APPVEYOR_PROJECT_NAME%" == "boost-ci" xcopy /s /e /q /i /y C:\boost-ci-cloned\ci .\ci
|
||||
- rmdir /s /q C:\boost-ci-cloned
|
||||
- ci\appveyor\install.bat
|
||||
|
||||
build: off
|
||||
|
||||
test_script: ci\build.bat
|
||||
|
||||
for:
|
||||
# CodeCov coverage build
|
||||
- matrix:
|
||||
only: [COVERAGE: true]
|
||||
test_script: [ps: ci\codecov.ps1]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Copyright 2019 - 2021 Alexander Grund
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Sample codecov configuration file. Edit as required
|
||||
|
||||
codecov:
|
||||
max_report_age: off
|
||||
require_ci_to_pass: yes
|
||||
notify:
|
||||
# Increase this if you have multiple coverage collection jobs
|
||||
after_n_builds: 1
|
||||
wait_for_ci: yes
|
||||
|
||||
# Change how pull request comments look
|
||||
comment:
|
||||
layout: "reach,diff,flags,files,footer"
|
||||
|
||||
# Ignore specific files or folders. Glob patterns are supported.
|
||||
# See https://docs.codecov.com/docs/ignoring-paths
|
||||
ignore:
|
||||
- extra/**/*
|
||||
# - test/**/*
|
||||
@@ -0,0 +1,491 @@
|
||||
# Copyright 2022 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
local library = "unordered";
|
||||
|
||||
local triggers =
|
||||
{
|
||||
branch: [ "master", "develop", "feature/*", "bugfix/*", "fix/*", "pr/*" ]
|
||||
};
|
||||
|
||||
local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' };
|
||||
local asan = { ASAN: '1' };
|
||||
local tsan = { TSAN: '1' };
|
||||
|
||||
local linux_pipeline(name, image, environment, packages = "", sources = [], arch = "amd64") =
|
||||
{
|
||||
name: name,
|
||||
kind: "pipeline",
|
||||
type: "docker",
|
||||
trigger: triggers,
|
||||
platform:
|
||||
{
|
||||
os: "linux",
|
||||
arch: arch
|
||||
},
|
||||
steps:
|
||||
[
|
||||
{
|
||||
name: "everything",
|
||||
image: image,
|
||||
environment: environment,
|
||||
commands:
|
||||
[
|
||||
'set -e',
|
||||
'uname -a',
|
||||
'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -',
|
||||
] +
|
||||
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
|
||||
(if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) +
|
||||
[
|
||||
'export LIBRARY=' + library,
|
||||
'./.drone/drone.sh',
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "catalina", arch = "amd64") =
|
||||
{
|
||||
name: name,
|
||||
kind: "pipeline",
|
||||
type: "exec",
|
||||
trigger: triggers,
|
||||
platform: {
|
||||
"os": "darwin",
|
||||
"arch": arch
|
||||
},
|
||||
node: {
|
||||
"os": osx_version
|
||||
},
|
||||
steps: [
|
||||
{
|
||||
name: "everything",
|
||||
environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" },
|
||||
commands:
|
||||
[
|
||||
'uname -a',
|
||||
'export LIBRARY=' + library,
|
||||
'./.drone/drone.sh',
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
local windows_pipeline(name, image, environment, arch = "amd64") =
|
||||
{
|
||||
name: name,
|
||||
kind: "pipeline",
|
||||
type: "docker",
|
||||
trigger: triggers,
|
||||
platform:
|
||||
{
|
||||
os: "windows",
|
||||
arch: arch
|
||||
},
|
||||
"steps":
|
||||
[
|
||||
{
|
||||
name: "everything",
|
||||
image: image,
|
||||
environment: environment,
|
||||
commands:
|
||||
[
|
||||
'echo $env:DRONE_STAGE_MACHINE',
|
||||
'cmd /C .drone\\\\drone.bat ' + library,
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
[
|
||||
linux_pipeline(
|
||||
"Linux 14.04 GCC 4.8* 32/64",
|
||||
"cppalliance/droneubuntu1404:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 14.04 GCC 4.9 32/64",
|
||||
"cppalliance/droneubuntu1404:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11', ADDRMD: '32,64' },
|
||||
"g++-4.9-multilib",
|
||||
[ "ppa:ubuntu-toolchain-r/test" ],
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 16.04 GCC 5* 32/64",
|
||||
"cppalliance/droneubuntu1604:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 GCC 6 32/64",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14', ADDRMD: '32,64' },
|
||||
"g++-6-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 GCC 7* 32/64",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 GCC 8 32/64 (11)",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11', ADDRMD: '32,64' },
|
||||
"g++-8-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 GCC 8 32/64 (14,17)",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '14,17', ADDRMD: '32,64' },
|
||||
"g++-8-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 9* 32/64 (11,14)",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 9* 32/64 (17,2a)",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '17,2a', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 9* ARM64",
|
||||
"cppalliance/droneubuntu2004:multiarch",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
|
||||
arch="arm64",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 9* S390x (11,14)",
|
||||
"cppalliance/droneubuntu2004:multiarch",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14' },
|
||||
arch="s390x",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 9* S390x (17,2a)",
|
||||
"cppalliance/droneubuntu2004:multiarch",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '17,2a' },
|
||||
arch="s390x",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 10 32/64 (11,14)",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14', ADDRMD: '32,64' },
|
||||
"g++-10-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 GCC 10 32/64 (17,20)",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '17,20', ADDRMD: '32,64' },
|
||||
"g++-10-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 11* 32/64 (11,14)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 11* 32/64 (17,2a)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '17,2a', ADDRMD: '32,64' },
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 32 ASAN (11,14)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11', ADDRMD: '32' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 32 ASAN (14)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '14', ADDRMD: '32' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 32 ASAN (17)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '17', ADDRMD: '32' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 32 ASAN (20)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '20', ADDRMD: '32' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 32 ASAN (2b)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '2b', ADDRMD: '32' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 64 ASAN (11,14)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14', ADDRMD: '64' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 64 ASAN (17)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '17', ADDRMD: '64' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 64 ASAN (20)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '20', ADDRMD: '64' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 64 ASAN (2b)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '2b', ADDRMD: '64' } + asan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 GCC 12 64 TSAN (11,14,17,20,2b)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14,17,20,2b', ADDRMD: '64', TARGET: 'libs/unordered/test//cfoa_tests' } + tsan,
|
||||
"g++-12-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.04 GCC 13 32/64 (11,14)",
|
||||
"cppalliance/droneubuntu2304:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14', ADDRMD: '32,64' },
|
||||
"g++-13 g++-13-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 23.04 GCC 13 32/64 (17,20,2b)",
|
||||
"cppalliance/droneubuntu2304:1",
|
||||
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '17,20,2b', ADDRMD: '32,64' },
|
||||
"g++-13 g++-13-multilib",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 16.04 Clang 3.5",
|
||||
"cppalliance/droneubuntu1604:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '11' },
|
||||
"clang-3.5",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 16.04 Clang 3.6",
|
||||
"cppalliance/droneubuntu1604:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '11,14' },
|
||||
"clang-3.6",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 16.04 Clang 3.7",
|
||||
"cppalliance/droneubuntu1604:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '11,14' },
|
||||
"clang-3.7",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 16.04 Clang 3.8",
|
||||
"cppalliance/droneubuntu1604:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '11,14' },
|
||||
"clang-3.8",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 Clang 3.9",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '11,14' },
|
||||
"clang-3.9",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 Clang 4.0",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '11,14' },
|
||||
"clang-4.0",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 Clang 5.0",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '11,14,1z' },
|
||||
"clang-5.0",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 18.04 Clang 6.0",
|
||||
"cppalliance/droneubuntu1804:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '11,14,17' },
|
||||
"clang-6.0",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 Clang 7",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '11,14,17' },
|
||||
"clang-7",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 Clang 8",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '11,14,17' },
|
||||
"clang-8",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 Clang 9",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '11,14,17,2a' },
|
||||
"clang-9",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 Clang 10",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '11,14,17,2a' },
|
||||
"clang-10",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 Clang 11",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '11,14,17,2a' },
|
||||
"clang-11",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 20.04 Clang 12",
|
||||
"cppalliance/droneubuntu2004:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '11,14,17,2a' },
|
||||
"clang-12",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 13",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20' },
|
||||
"clang-13",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 UBSAN (11,14)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14' } + ubsan,
|
||||
"clang-14",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 UBSAN (17,20)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '17,20' } + ubsan,
|
||||
"clang-14",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 ASAN (11,14)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14' } + asan,
|
||||
"clang-14",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 ASAN (17,20)",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '17,20' } + asan,
|
||||
"clang-14",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 14 libc++ 64 TSAN",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-14', ADDRMD: '64', TARGET: 'libs/unordered/test//cfoa_tests', CXXSTD: '11,14,17,20', STDLIB: 'libc++' } + tsan,
|
||||
"clang-14 libc++-14-dev libc++abi-14-dev",
|
||||
),
|
||||
|
||||
linux_pipeline(
|
||||
"Linux 22.04 Clang 15",
|
||||
"cppalliance/droneubuntu2204:1",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' },
|
||||
"clang-15",
|
||||
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"],
|
||||
),
|
||||
|
||||
macos_pipeline(
|
||||
"MacOS 10.15 Xcode 12.2 UBSAN (11)",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11' } + ubsan,
|
||||
),
|
||||
|
||||
macos_pipeline(
|
||||
"MacOS 10.15 Xcode 12.2 UBSAN (14)",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '14' } + ubsan,
|
||||
),
|
||||
|
||||
macos_pipeline(
|
||||
"MacOS 10.15 Xcode 12.2 UBSAN (1z)",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '1z' } + ubsan,
|
||||
),
|
||||
|
||||
macos_pipeline(
|
||||
"MacOS 12.4 Xcode 13.4.1 ASAN",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + asan,
|
||||
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
|
||||
),
|
||||
|
||||
macos_pipeline(
|
||||
"MacOS 12.4 Xcode 13.4.1 TSAN",
|
||||
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z', TARGET: 'libs/unordered/test//cfoa_tests' } + tsan,
|
||||
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
|
||||
),
|
||||
|
||||
windows_pipeline(
|
||||
"Windows VS2015 msvc-14.0",
|
||||
"cppalliance/dronevs2015",
|
||||
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest' },
|
||||
),
|
||||
|
||||
windows_pipeline(
|
||||
"Windows VS2017 msvc-14.1",
|
||||
"cppalliance/dronevs2017",
|
||||
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest' },
|
||||
),
|
||||
|
||||
windows_pipeline(
|
||||
"Windows VS2019 msvc-14.2",
|
||||
"cppalliance/dronevs2019",
|
||||
{ TOOLSET: 'msvc-14.2', CXXSTD: '14,17,20,latest' },
|
||||
),
|
||||
|
||||
windows_pipeline(
|
||||
"Windows VS2022 msvc-14.3",
|
||||
"cppalliance/dronevs2022:1",
|
||||
{ TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' },
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
@REM Copyright 2022 Peter Dimov
|
||||
@REM Distributed under the Boost Software License, Version 1.0.
|
||||
@REM https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
@ECHO ON
|
||||
|
||||
set LIBRARY=%1
|
||||
set DRONE_BUILD_DIR=%CD%
|
||||
|
||||
set BOOST_BRANCH=develop
|
||||
if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
git submodule update --init tools/boostdep
|
||||
xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\
|
||||
python tools/boostdep/depinst/depinst.py %LIBRARY%
|
||||
cmd /c bootstrap
|
||||
b2 -d0 headers
|
||||
|
||||
if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
b2 --abbreviate-paths -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright 2022 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
set -ex
|
||||
export PATH=~/.local/bin:/usr/local/bin:$PATH
|
||||
|
||||
: ${TARGET:="libs/$LIBRARY/test"}
|
||||
|
||||
DRONE_BUILD_DIR=$(pwd)
|
||||
|
||||
BOOST_BRANCH=develop
|
||||
if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi
|
||||
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
git submodule update --init tools/boostdep
|
||||
cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY
|
||||
python tools/boostdep/depinst/depinst.py $LIBRARY
|
||||
./bootstrap.sh
|
||||
./b2 -d0 headers
|
||||
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
./b2 -j3 $TARGET toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${STDLIB:+stdlib=$STDLIB} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${TSAN:+thread-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
@@ -0,0 +1,7 @@
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
|
||||
[*.?pp]
|
||||
indent_size = 2
|
||||
@@ -0,0 +1,440 @@
|
||||
# Copyright 2020-2021 Peter Dimov
|
||||
# Copyright 2021 Andrey Semashev
|
||||
# Copyright 2021 Alexander Grund
|
||||
# Copyright 2022 James E. King III
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
---
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- bugfix/**
|
||||
- feature/**
|
||||
- fix/**
|
||||
- pr/**
|
||||
|
||||
concurrency:
|
||||
group: ${{format('{0}:{1}', github.repository, github.ref)}}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
GIT_FETCH_JOBS: 8
|
||||
NET_RETRY_COUNT: 5
|
||||
B2_CI_VERSION: 1
|
||||
B2_VARIANT: debug,release
|
||||
LCOV_BRANCH_COVERAGE: 0
|
||||
CODECOV_NAME: Github Actions
|
||||
|
||||
jobs:
|
||||
runner-selection:
|
||||
# runs-on: ubuntu-latest
|
||||
runs-on: ${{ github.repository_owner == 'boostorg' && fromJSON('[ "self-hosted", "linux", "x64", "ubuntu-latest-aws" ]') || 'ubuntu-latest' }}
|
||||
outputs:
|
||||
labelmatrix: ${{ steps.aws_hosted_runners.outputs.labelmatrix }}
|
||||
steps:
|
||||
- name: AWS Hosted Runners
|
||||
id: aws_hosted_runners
|
||||
uses: cppalliance/aws-hosted-runners@v1.0.0
|
||||
|
||||
posix:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Linux, gcc
|
||||
- { compiler: gcc-7, cxxstd: '11,14,17', os: 'ubuntu-20.04', install: 'g++-7' }
|
||||
- { compiler: gcc-8, cxxstd: '11,14,17', os: 'ubuntu-20.04', install: 'g++-8' }
|
||||
- { compiler: gcc-9, cxxstd: '11,14,17', os: 'ubuntu-22.04', install: 'g++-9' }
|
||||
- { compiler: gcc-10, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', install: 'g++-10' }
|
||||
- { compiler: gcc-11, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', install: 'g++-11' }
|
||||
- { name: "gcc-12 w/ sanitizers (11)", sanitize: yes,
|
||||
compiler: gcc-12, cxxstd: '11', os: 'ubuntu-22.04', ccache_key: "san1" }
|
||||
- { name: "gcc-12 w/ sanitizers (14)", sanitize: yes,
|
||||
compiler: gcc-12, cxxstd: '14', os: 'ubuntu-22.04', ccache_key: "san1" }
|
||||
- { name: "gcc-12 w/ sanitizers (17)", sanitize: yes,
|
||||
compiler: gcc-12, cxxstd: '17', os: 'ubuntu-22.04', ccache_key: "san2" }
|
||||
- { name: "gcc-12 w/ sanitizers (20)", sanitize: yes,
|
||||
compiler: gcc-12, cxxstd: '20', os: 'ubuntu-22.04', ccache_key: "san2" }
|
||||
- { name: "gcc-12 w/ sanitizers (2b)", sanitize: yes,
|
||||
compiler: gcc-12, cxxstd: '2b', os: 'ubuntu-22.04', ccache_key: "san2" }
|
||||
- { name: Collect coverage, coverage: yes,
|
||||
compiler: gcc-12, cxxstd: '20', os: 'ubuntu-22.04', install: 'g++-12-multilib', address-model: '32,64', ccache_key: "cov" }
|
||||
|
||||
- { name: "cfoa tsan (gcc-12)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: gcc-12,
|
||||
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes, ccache_key: "tsan" }
|
||||
|
||||
# Linux, clang, libc++
|
||||
- { compiler: clang-7, cxxstd: '11,14,17', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-7 libc++-7-dev libc++abi-7-dev' }
|
||||
- { compiler: clang-10, cxxstd: '11,14,17,20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-10 libc++-10-dev libc++abi-10-dev' }
|
||||
- { compiler: clang-11, cxxstd: '11,14,17,20', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-11 libc++-11-dev libc++abi-11-dev' }
|
||||
# clang-12 doesn't work on 'ubuntu-22.04', the linker can't find -lunwind for some reason
|
||||
- { name: "clang-12 w/ sanitizers (11,14)", sanitize: yes,
|
||||
compiler: clang-12, cxxstd: '11,14', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san1" }
|
||||
- { name: "clang-12 w/ sanitizers (17)", sanitize: yes,
|
||||
compiler: clang-12, cxxstd: '17', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
|
||||
- { name: "clang-12 w/ sanitizers (20)", sanitize: yes,
|
||||
compiler: clang-12, cxxstd: '20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
|
||||
- { name: "clang-12 w/ sanitizers (2b)", sanitize: yes,
|
||||
compiler: clang-12, cxxstd: '2b', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
|
||||
- { compiler: 'clang-13', cxxstd: '11,14', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
|
||||
- { compiler: 'clang-13', cxxstd: '17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
|
||||
|
||||
# not using libc++ because of https://github.com/llvm/llvm-project/issues/52771
|
||||
- { name: "clang-14 w/ sanitizers (11,14)", sanitize: yes,
|
||||
compiler: clang-14, cxxstd: '11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
|
||||
- { name: "clang-14 w/ sanitizers (17)", sanitize: yes,
|
||||
compiler: clang-14, cxxstd: '17', os: 'ubuntu-22.04', ccache_key: "san2" }
|
||||
- { name: "clang-14 w/ sanitizers (20)", sanitize: yes,
|
||||
compiler: clang-14, cxxstd: '20', container: 'ubuntu:22.04', os: 'ubuntu-latest', ccache_key: "san2" }
|
||||
- { name: "clang-14 w/ sanitizers (2b)", sanitize: yes,
|
||||
compiler: clang-14, cxxstd: '2b', container: 'ubuntu:22.04', os: 'ubuntu-latest', ccache_key: "san2" }
|
||||
|
||||
- { name: "cfoa tsan (clang-14)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: clang-14,
|
||||
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes,
|
||||
stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev', ccache_key: "tsan" }
|
||||
|
||||
- { compiler: 'clang-15', cxxstd: '11,14', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-15 libc++-15-dev libc++abi-15-dev' }
|
||||
- { compiler: 'clang-15', cxxstd: '17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-15 libc++-15-dev libc++abi-15-dev' }
|
||||
|
||||
# OSX, clang
|
||||
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-11' }
|
||||
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-12', sanitize: yes, ccache_key: "san1" }
|
||||
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-12', thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests', ccache_key: "tsan" }
|
||||
- { compiler: clang, cxxstd: '11,14,17,20,2b', os: 'macos-13' }
|
||||
|
||||
timeout-minutes: 360
|
||||
# posix (gcc-12 w/ sanitizers is taking longer than 210 minutes
|
||||
# timeout-minutes: 210
|
||||
needs: [runner-selection]
|
||||
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
|
||||
container: ${{matrix.container}}
|
||||
env: {B2_USE_CCACHE: 1}
|
||||
|
||||
steps:
|
||||
- name: Setup environment
|
||||
run: |
|
||||
if [ -f "/etc/debian_version" ]; then
|
||||
echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
fi
|
||||
if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common
|
||||
# Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80
|
||||
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E1DD270288B4E6030699E45FA1715D88E1DF1F24
|
||||
for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python-is-python3 git
|
||||
fi
|
||||
# For jobs not compatible with ccache, use "ccache: no" in the matrix
|
||||
if [[ "${{ matrix.ccache }}" == "no" ]]; then
|
||||
echo "B2_USE_CCACHE=0" >> $GITHUB_ENV
|
||||
fi
|
||||
git config --global pack.threads 0
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary'
|
||||
fetch-depth: ${{ matrix.coverage && '0' || '1' }}
|
||||
|
||||
- name: Cache ccache
|
||||
uses: actions/cache@v3
|
||||
if: env.B2_USE_CCACHE
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{matrix.ccache_key}}-${{github.sha}}
|
||||
restore-keys: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{matrix.ccache_key}}-
|
||||
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
||||
rm -rf boost-ci-cloned
|
||||
|
||||
- name: Install packages
|
||||
if: startsWith(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}})
|
||||
SOURCES=(${{join(matrix.sources, ' ')}})
|
||||
# Add this by default
|
||||
SOURCES+=(ppa:ubuntu-toolchain-r/test)
|
||||
for key in "${SOURCE_KEYS[@]}"; do
|
||||
for i in {1..$NET_RETRY_COUNT}; do
|
||||
wget -O - "$key" | sudo apt-key add - && break || sleep 10
|
||||
done
|
||||
done
|
||||
for source in "${SOURCES[@]}"; do
|
||||
for i in {1..$NET_RETRY_COUNT}; do
|
||||
sudo add-apt-repository $source && break || sleep 10
|
||||
done
|
||||
done
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update
|
||||
if [[ -z "${{matrix.install}}" ]]; then
|
||||
pkgs="${{matrix.compiler}}"
|
||||
pkgs="${pkgs/gcc-/g++-}"
|
||||
else
|
||||
pkgs="${{matrix.install}}"
|
||||
fi
|
||||
sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs
|
||||
|
||||
- name: Setup GCC Toolchain
|
||||
if: matrix.gcc_toolchain
|
||||
run: |
|
||||
GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain"
|
||||
echo "GCC_TOOLCHAIN_ROOT=$GCC_TOOLCHAIN_ROOT" >> $GITHUB_ENV
|
||||
MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)"
|
||||
mkdir -p "$GCC_TOOLCHAIN_ROOT"
|
||||
ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include"
|
||||
ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin"
|
||||
mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET"
|
||||
ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}"
|
||||
|
||||
- name: Setup multiarch
|
||||
if: matrix.multiarch
|
||||
run: |
|
||||
sudo apt-get install --no-install-recommends -y binfmt-support qemu-user-static
|
||||
sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||
git clone https://github.com/jeking3/bdde.git
|
||||
echo "$(pwd)/bdde/bin/linux" >> ${GITHUB_PATH}
|
||||
echo "BDDE_DISTRO=${{ matrix.distro }}" >> ${GITHUB_ENV}
|
||||
echo "BDDE_EDITION=${{ matrix.edition }}" >> ${GITHUB_ENV}
|
||||
echo "BDDE_ARCH=${{ matrix.arch }}" >> ${GITHUB_ENV}
|
||||
echo "B2_WRAPPER=bdde" >> ${GITHUB_ENV}
|
||||
|
||||
- name: Setup Boost
|
||||
env:
|
||||
B2_ADDRESS_MODEL: ${{matrix.address-model}}
|
||||
B2_COMPILER: ${{matrix.compiler}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_SANITIZE: ${{matrix.sanitize}}
|
||||
B2_TSAN: ${{matrix.thread-sanitize}}
|
||||
B2_TARGETS: ${{matrix.targets}}
|
||||
B2_STDLIB: ${{matrix.stdlib}}
|
||||
# More entries can be added in the same way, see the B2_ARGS assignment in ci/enforce.sh for the possible keys.
|
||||
# B2_DEFINES: ${{matrix.defines}}
|
||||
# Variables set here (to non-empty) will override the top-level environment variables, e.g.
|
||||
# B2_VARIANT: ${{matrix.variant}}
|
||||
run: source ci/github/install.sh
|
||||
|
||||
- name: Setup coverage collection
|
||||
if: matrix.coverage
|
||||
run: ci/github/codecov.sh "setup"
|
||||
|
||||
- name: Run tests
|
||||
if: '!matrix.coverity'
|
||||
run: B2_TARGETS=${{matrix.targets}} ci/build.sh
|
||||
|
||||
- name: Upload coverage
|
||||
if: matrix.coverage
|
||||
run: ci/codecov.sh "upload"
|
||||
|
||||
- name: Run coverity
|
||||
if: matrix.coverity && github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'master')
|
||||
run: ci/github/coverity.sh
|
||||
env:
|
||||
COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }}
|
||||
COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
|
||||
|
||||
windows:
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { toolset: msvc-14.0, cxxstd: '14,latest', addrmd: '32,64', os: 'windows-2019', variant: 'debug,release' }
|
||||
- { toolset: msvc-14.2, cxxstd: '14,17,20,latest', addrmd: '32,64', os: 'windows-2019', variant: 'debug,release' }
|
||||
- { toolset: msvc-14.3, cxxstd: '14,17,20,latest', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release' }
|
||||
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '64', os: 'windows-2022', variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '/RTCc' }
|
||||
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '32', os: 'windows-2022', variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '"/RTCc /arch:IA32"' }
|
||||
- { toolset: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release' }
|
||||
- { toolset: gcc, cxxstd: '11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' }
|
||||
|
||||
needs: [runner-selection]
|
||||
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
REM Copy ci folder if not testing Boost.CI
|
||||
if "%GITHUB_REPOSITORY%" == "%GITHUB_REPOSITORY:boost-ci=%" xcopy /s /e /q /i /y boost-ci-cloned\ci .\ci
|
||||
rmdir /s /q boost-ci-cloned
|
||||
|
||||
- name: Setup Boost
|
||||
run: ci\github\install.bat
|
||||
|
||||
- name: Run tests
|
||||
if: '!matrix.coverage'
|
||||
run: ci\build.bat
|
||||
env:
|
||||
B2_TOOLSET: ${{matrix.toolset}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_ADDRESS_MODEL: ${{matrix.addrmd}}
|
||||
B2_DEFINES: ${{matrix.defines}}
|
||||
B2_VARIANT: ${{matrix.variant}}
|
||||
B2_CXXFLAGS: ${{matrix.cxxflags}}
|
||||
|
||||
- name: Collect coverage
|
||||
shell: powershell
|
||||
if: matrix.coverage
|
||||
run: ci\opencppcoverage.ps1
|
||||
env:
|
||||
B2_TOOLSET: ${{matrix.toolset}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_ADDRESS_MODEL: ${{matrix.addrmd}}
|
||||
|
||||
- name: Upload coverage
|
||||
if: matrix.coverage
|
||||
uses: codecov/codecov-action@v2
|
||||
with:
|
||||
files: __out/cobertura.xml
|
||||
|
||||
MSYS2:
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { sys: MINGW32, compiler: gcc, cxxstd: '11,17,20' }
|
||||
- { sys: MINGW64, compiler: gcc, cxxstd: '11,17,20' }
|
||||
|
||||
needs: [runner-selection]
|
||||
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['windows-latest'] }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup MSYS2 environment
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{matrix.sys}}
|
||||
update: true
|
||||
install: git python
|
||||
pacboy: gcc:p cmake:p ninja:p
|
||||
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
||||
rm -rf boost-ci-cloned
|
||||
|
||||
- name: Setup Boost
|
||||
env:
|
||||
B2_COMPILER: ${{matrix.compiler}}
|
||||
B2_CXXSTD: ${{matrix.cxxstd}}
|
||||
B2_SANITIZE: ${{matrix.sanitize}}
|
||||
B2_STDLIB: ${{matrix.stdlib}}
|
||||
run: ci/github/install.sh
|
||||
|
||||
- name: Run tests
|
||||
run: ci/build.sh
|
||||
|
||||
# Run also the CMake tests to avoid having to setup another matrix for CMake on MSYS
|
||||
- name: Run CMake tests
|
||||
run: |
|
||||
cd "$BOOST_ROOT"
|
||||
mkdir __build_cmake_test__ && cd __build_cmake_test__
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=ON -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ..
|
||||
cmake --build . --target tests --config Debug -j$B2_JOBS
|
||||
ctest --output-on-failure --build-config Debug
|
||||
|
||||
CMake:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { os: 'ubuntu-20.04', build_shared: ON, build_type: Debug, generator: 'Unix Makefiles' }
|
||||
- { os: 'windows-2019', build_shared: ON, build_type: Debug, generator: 'Visual Studio 16 2019' }
|
||||
|
||||
timeout-minutes: 120
|
||||
needs: [runner-selection]
|
||||
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Fetch Boost.CI
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: boostorg/boost-ci
|
||||
ref: master
|
||||
path: boost-ci-cloned
|
||||
- name: Get CI scripts folder
|
||||
run: |
|
||||
# Copy ci folder if not testing Boost.CI
|
||||
[[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci .
|
||||
rm -rf boost-ci-cloned
|
||||
- name: Setup Boost
|
||||
env: {B2_DONT_BOOTSTRAP: 1}
|
||||
run: source ci/github/install.sh
|
||||
|
||||
- name: Run CMake tests
|
||||
run: |
|
||||
cd "$BOOST_ROOT"
|
||||
mkdir __build_cmake_test__ && cd __build_cmake_test__
|
||||
cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON ..
|
||||
cmake --build . --target tests --config ${{matrix.build_type}} -j$B2_JOBS
|
||||
ctest --output-on-failure --build-config ${{matrix.build_type}}
|
||||
|
||||
- name: Run CMake subdir tests
|
||||
run: |
|
||||
cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_test" # New unified folder
|
||||
[ -d "$cmake_test_folder" ] || cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_subdir_test"
|
||||
cd "$cmake_test_folder"
|
||||
mkdir __build_cmake_subdir_test__ && cd __build_cmake_subdir_test__
|
||||
cmake -G "${{matrix.generator}}" -DBOOST_CI_INSTALL_TEST=OFF -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.build_shared}} ..
|
||||
cmake --build . --config ${{matrix.build_type}} -j$B2_JOBS
|
||||
ctest --output-on-failure --build-config ${{matrix.build_type}}
|
||||
|
||||
- name: Install Library
|
||||
run: |
|
||||
cd "$BOOST_ROOT"
|
||||
mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__
|
||||
cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DCMAKE_INSTALL_PREFIX=~/.local -DBoost_VERBOSE=ON -DBoost_DEBUG=ON ..
|
||||
cmake --build . --target install --config ${{matrix.build_type}} -j$B2_JOBS
|
||||
- name: Run CMake install tests
|
||||
run: |
|
||||
cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_test" # New unified folder
|
||||
[ -d "$cmake_test_folder" ] || cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_install_test"
|
||||
cd "$cmake_test_folder"
|
||||
mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__
|
||||
cmake -G "${{matrix.generator}}" -DBOOST_CI_INSTALL_TEST=ON -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DCMAKE_PREFIX_PATH=~/.local ..
|
||||
cmake --build . --config ${{matrix.build_type}} -j$B2_JOBS
|
||||
ctest --output-on-failure --build-config ${{matrix.build_type}}
|
||||
@@ -0,0 +1,2 @@
|
||||
/doc/html/
|
||||
/doc/pdf/
|
||||
@@ -0,0 +1,87 @@
|
||||
# Copyright (C) 2016 Daniel James.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Use Trusty to get a reasonably recent version of Boost.
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
language: c++
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libxml2-utils
|
||||
- g++-multilib
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
env: |
|
||||
label="gcc C++03/11";
|
||||
user_config="using gcc : : g++-4.8 --coverage -fsanitize=address ;"
|
||||
enable_coverage=1
|
||||
CXXSTD=03,11
|
||||
- compiler: gcc
|
||||
env: |
|
||||
label="gcc 32 bit C++11";
|
||||
user_config="using gcc : : g++-4.8 -m32 -fsanitize=address ;"
|
||||
CXXSTD=11
|
||||
- compiler: clang
|
||||
env: |
|
||||
label="clang C++11/17";
|
||||
user_config="using clang : : clang++ -fsanitize=address ;"
|
||||
CXXSTD=11,17
|
||||
# sanitized=address not available for 32-bit clang on travis.
|
||||
- compiler: clang
|
||||
env: |
|
||||
label="clang 32 bit";
|
||||
user_config="using clang : : clang++ -m32 ;"
|
||||
CXXSTD=03
|
||||
|
||||
before_install:
|
||||
- if [ -n $enable_coverage ]; then pip install --user cpp-coveralls; fi
|
||||
|
||||
before_script:
|
||||
- export BOOST_VERSION=1.67.0
|
||||
- export BOOST_FILENAME=boost_1_67_0
|
||||
- export BOOST_ROOT=${HOME}/boost
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
- touch Jamroot.jam
|
||||
- cd $HOME
|
||||
- echo $user_config > ~/user-config.jam
|
||||
- cat ~/user-config.jam
|
||||
- |
|
||||
# Pick snapshot to use
|
||||
if [ "$TRAVIS_EVENT_TYPE" == "cron" ]
|
||||
then
|
||||
if [ "$TRAVIS_BRANCH" == "master" ]
|
||||
then
|
||||
snapshot=master
|
||||
else
|
||||
snapshot=develop
|
||||
fi
|
||||
else
|
||||
#snapshot=stable
|
||||
snapshot=master
|
||||
fi
|
||||
|
||||
# Download and extract snapshot
|
||||
echo "Downloading ${download_url}"
|
||||
mkdir $HOME/download
|
||||
cd $HOME/download
|
||||
python ${TRAVIS_BUILD_DIR}/ci/download-boost-snapshot.py $snapshot
|
||||
mv * ${BOOST_ROOT}
|
||||
- rm -r ${BOOST_ROOT}/boost/unordered
|
||||
- cd ${BOOST_ROOT}/tools/build
|
||||
- mkdir ${HOME}/opt
|
||||
- bash bootstrap.sh
|
||||
- ./b2 install --prefix=$HOME/opt
|
||||
|
||||
after_success:
|
||||
if [ -n $enable_coverage ]; then coveralls -r ${TRAVIS_BUILD_DIR} -b ${TRAVIS_BUILD_DIR}/test --gcov-options '\-lp' --include include/boost/unordered/ ; fi
|
||||
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}/test
|
||||
- ${HOME}/opt/bin/b2 -j 3 cxxstd=$CXXSTD -q include=${BOOST_ROOT} include=${TRAVIS_BUILD_DIR}/include
|
||||
- xmllint --noout ${TRAVIS_BUILD_DIR}/doc/ref.xml
|
||||
@@ -0,0 +1,35 @@
|
||||
# Generated by `boostdep --cmake unordered`
|
||||
# Copyright 2020, 2021 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.20)
|
||||
|
||||
project(boost_unordered VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
|
||||
|
||||
add_library(boost_unordered INTERFACE)
|
||||
add_library(Boost::unordered ALIAS boost_unordered)
|
||||
|
||||
target_include_directories(boost_unordered INTERFACE include)
|
||||
|
||||
target_link_libraries(boost_unordered
|
||||
INTERFACE
|
||||
Boost::assert
|
||||
Boost::config
|
||||
Boost::container_hash
|
||||
Boost::core
|
||||
Boost::move
|
||||
Boost::mp11
|
||||
Boost::predef
|
||||
Boost::preprocessor
|
||||
Boost::static_assert
|
||||
Boost::throw_exception
|
||||
Boost::tuple
|
||||
Boost::type_traits
|
||||
)
|
||||
|
||||
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
|
||||
|
||||
add_subdirectory(test)
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Boost.Unordered
|
||||
|
||||
[](https://github.com/boostorg/unordered/tree/master) [](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [](https://drone.cpp.al/boostorg/unordered) [](https://ci.appveyor.com/project/cppalliance/unordered/branch/master) [](https://codecov.io/gh/boostorg/unordered/branch/master) [](https://pdimov.github.io/boostdep-report/master/unordered.html) [](https://www.boost.org/doc/libs/master/libs/unordered/doc/html/unordered.html) [](http://www.boost.org/development/tests/master/developer/unordered.html)<br/>
|
||||
[](https://github.com/boostorg/unordered/tree/develop) [](https://github.com/boostorg/unordered/actions/workflows/ci.yml) [](https://drone.cpp.al/boostorg/unordered) [](https://ci.appveyor.com/project/cppalliance/unordered/branch/develop) [](https://codecov.io/gh/boostorg/unordered/branch/develop) [](https://pdimov.github.io/boostdep-report/develop/unordered.html) [](https://www.boost.org/doc/libs/develop/libs/unordered/doc/html/unordered.html) [](http://www.boost.org/development/tests/develop/developer/unordered.html)<br/>
|
||||
[](https://www.boost.org/users/license.html) <img alt="C++11 required" src="https://img.shields.io/badge/standard-C%2b%2b11-blue.svg"> <img alt="Header-only library" src="https://img.shields.io/badge/build-header--only-blue.svg">
|
||||
|
||||
Boost.Unordered offers a catalog of hash containers with different standards compliance levels, performances and intented usage scenarios:
|
||||
|
||||
**`boost::unordered_set` `boost::unordered_map` `boost::unordered_multiset` `boost::unordered_multimap`**
|
||||
|
||||
<ul>Fully conformant implementations of <code>std::unordered_[multi](set|map)</code>,
|
||||
but faster and up to the latest revisions of the standard even if you're working in an older version of C++ (heterogeneous lookup,
|
||||
<code>try_emplace</code>, <code>contains</code>, etc.)</ul>
|
||||
|
||||
**`boost::unordered_flat_set` `boost::unordered_flat_map`**
|
||||
|
||||
<ul>The fastest of the lot. Based on open addressing, these containers slightly
|
||||
deviate from the standard in exchange for top performance.</ul>
|
||||
|
||||
**`boost::unordered_node_set` `boost::unordered_node_map`**
|
||||
|
||||
<ul>Variations of <code>boost::unordered_flat_(set|map)</code> providing pointer stability.</ul>
|
||||
|
||||
**`boost::concurrent_flat_set` `boost::concurrent_flat_map`**
|
||||
|
||||
<ul>High performance for multithreaded scenarios. Introducing a new non-standard, iterator-free API.</ul>
|
||||
|
||||
## Learn about Boost.Unordered
|
||||
|
||||
* [Online documentation](https://boost.org/libs/unordered)
|
||||
* [Some benchmarks](https://github.com/boostorg/boost_unordered_benchmarks)
|
||||
* Technical articles on Boost.Unordered internal design:
|
||||
* [Advancing the state of the art for `std::unordered_map` implementations](https://bannalia.blogspot.com/2022/06/advancing-state-of-art-for.html)
|
||||
* [Inside `boost::unordered_flat_map`](https://bannalia.blogspot.com/2022/11/inside-boostunorderedflatmap.html)
|
||||
* [Inside `boost::concurrent_flat_map`](https://bannalia.blogspot.com/2023/07/inside-boostconcurrentflatmap.html)
|
||||
* [Bulk visitation in `boost::concurrent_flat_map`](https://bannalia.blogspot.com/2023/10/bulk-visitation-in-boostconcurrentflatm.html)
|
||||
|
||||
## Get the library
|
||||
|
||||
Boost.Unordered can be installed in a number of ways:
|
||||
|
||||
* [Download Boost](https://www.boost.org/users/download/) and you're ready to go (this is a header-only library requiring no building).
|
||||
* Using Conan 2: In case you don't have it yet, add an entry for Boost in your `conanfile.txt` (the example requires at least Boost 1.83):
|
||||
```
|
||||
[requires]
|
||||
boost/[>=1.83.0]
|
||||
```
|
||||
<ul>If you're not using any compiled Boost library, the following will skip building altogether:</ul>
|
||||
|
||||
```
|
||||
[options]
|
||||
boost:header_only=True
|
||||
```
|
||||
* Using vcpkg: Execute the command
|
||||
```
|
||||
vcpkg install boost-unordered
|
||||
```
|
||||
* Using CMake: [Boost CMake support infrastructure](https://github.com/boostorg/cmake)
|
||||
allows you to use CMake directly to download, build and consume all of Boost or
|
||||
some specific libraries.
|
||||
|
||||
## Support
|
||||
|
||||
* Join the **#boost-unordered** discussion group at [cpplang.slack.com](https://cpplang.slack.com/)
|
||||
([ask for an invite](https://cppalliance.org/slack/) if you’re not a member of this workspace yet)
|
||||
* Ask in the [Boost Users mailing list](https://lists.boost.org/mailman/listinfo.cgi/boost-users)
|
||||
(add the `[unordered]` tag at the beginning of the subject line)
|
||||
* [File an issue](https://github.com/boostorg/unordered/issues)
|
||||
|
||||
## Contribute
|
||||
|
||||
* [Pull requests](https://github.com/boostorg/unordered/pulls) against **develop** branch are most welcome.
|
||||
Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
# Copyright 2017 Daniel James.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
# Using clang format 4.0
|
||||
# http://llvm.org/releases/4.0.0/tools/clang/docs/ClangFormatStyleOptions.html
|
||||
|
||||
# Becuase you have to start somewhere.
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
# Basic settings
|
||||
ColumnLimit: 80
|
||||
NamespaceIndentation: All
|
||||
ContinuationIndentWidth: 2
|
||||
IndentWidth: 2
|
||||
UseTab: Never
|
||||
Language: Cpp
|
||||
Standard: Cpp03
|
||||
|
||||
# Code layout
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignTrailingComments: true
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterNamespace: false
|
||||
AfterClass: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterControlStatement: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
PointerAlignment: Left
|
||||
|
||||
# Boost specific stuff
|
||||
ForEachMacros: [ BOOST_FOREACH, UNORDERED_AUTO_TEST ]
|
||||
@@ -0,0 +1,3 @@
|
||||
enwik8
|
||||
enwik9
|
||||
*.exe
|
||||
@@ -0,0 +1,431 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::uint32_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
constexpr unsigned N = 2'000'000;
|
||||
constexpr int K = 10;
|
||||
|
||||
static std::vector<std::string> indices1, indices2;
|
||||
|
||||
static std::string make_index( unsigned x )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
std::snprintf( buffer, sizeof(buffer), "pfx_%u_sfx", x );
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static std::string make_random_index( unsigned x )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
std::snprintf( buffer, sizeof(buffer), "pfx_%0*d_%u_sfx", x % 8 + 1, 0, x );
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void init_indices()
|
||||
{
|
||||
indices1.reserve( N*2+1 );
|
||||
indices1.push_back( make_index( 0 ) );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices1.push_back( make_index( i ) );
|
||||
}
|
||||
|
||||
indices2.reserve( N*2+1 );
|
||||
indices2.push_back( make_index( 0 ) );
|
||||
|
||||
{
|
||||
boost::detail::splitmix64 rng;
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices2.push_back( make_random_index( static_cast<std::uint32_t>( rng() ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices1[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices2[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Random insert", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::uint32_t s;
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices1[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices2[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Random lookup", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
auto it = map.begin();
|
||||
|
||||
while( it != map.end() )
|
||||
{
|
||||
if( it->second & 1 )
|
||||
{
|
||||
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
|
||||
{
|
||||
map.erase( it++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
it = map.erase( it );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and erase odd elements", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices1[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices2[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Random erase", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<std::string, std::uint32_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_insert( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_lookup( map, t1 );
|
||||
test_iteration( map, t1 );
|
||||
test_lookup( map, t1 );
|
||||
test_erase( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
|
||||
template<> struct fnv1a_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string const& s ) const
|
||||
{
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x01000193ul;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct fnv1a_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string const& s ) const
|
||||
{
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x00000100000001B3ull;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits >
|
||||
{
|
||||
using is_avalanching = void;
|
||||
};
|
||||
|
||||
template<class K, class V> using std_unordered_map_fnv1a =
|
||||
std::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map_fnv1a =
|
||||
boost::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map_fnv1a =
|
||||
boost::unordered_node_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map_fnv1a =
|
||||
boost::unordered_flat_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map_fnv1a =
|
||||
absl::node_hash_map<K, V, fnv1a_hash, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map_fnv1a =
|
||||
absl::flat_hash_map<K, V, fnv1a_hash, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map_fnv1a =
|
||||
ankerl::unordered_dense::map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
int main()
|
||||
{
|
||||
init_indices();
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
|
||||
test<boost_unordered_map_fnv1a>( "boost::unordered_map, FNV-1a" );
|
||||
test<boost_unordered_node_map_fnv1a>( "boost::unordered_node_map, FNV-1a" );
|
||||
test<boost_unordered_flat_map_fnv1a>( "boost::unordered_flat_map, FNV-1a" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map_fnv1a>( "ankerl::unordered_dense::map, FNV-1a" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map_fnv1a>( "absl::node_hash_map, FNV-1a" );
|
||||
test<absl_flat_hash_map_fnv1a>( "absl::flat_hash_map, FNV-1a" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 38 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -0,0 +1,432 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::uint32_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
constexpr unsigned N = 2'000'000;
|
||||
constexpr int K = 10;
|
||||
|
||||
static std::vector<std::string> indices1, indices2;
|
||||
|
||||
static std::string make_index( unsigned x )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
std::snprintf( buffer, sizeof(buffer), "pfx_%u_sfx", x );
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static std::string make_random_index( unsigned x )
|
||||
{
|
||||
char buffer[ 64 ];
|
||||
std::snprintf( buffer, sizeof(buffer), "pfx_%0*d_%u_sfx", x % 8 + 1, 0, x );
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void init_indices()
|
||||
{
|
||||
indices1.reserve( N*2+1 );
|
||||
indices1.push_back( make_index( 0 ) );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices1.push_back( make_index( i ) );
|
||||
}
|
||||
|
||||
indices2.reserve( N*2+1 );
|
||||
indices2.push_back( make_index( 0 ) );
|
||||
|
||||
{
|
||||
boost::detail::splitmix64 rng;
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices2.push_back( make_random_index( static_cast<std::uint32_t>( rng() ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices1[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices2[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Random insert", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::uint32_t s;
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices1[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices2[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Random lookup", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
auto it = map.begin();
|
||||
|
||||
while( it != map.end() )
|
||||
{
|
||||
if( it->second & 1 )
|
||||
{
|
||||
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
|
||||
{
|
||||
map.erase( it++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
it = map.erase( it );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and erase odd elements", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices1[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices2[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Random erase", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<std::string_view, std::uint32_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_insert( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_lookup( map, t1 );
|
||||
test_iteration( map, t1 );
|
||||
test_lookup( map, t1 );
|
||||
test_erase( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
|
||||
template<> struct fnv1a_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string_view const& s ) const
|
||||
{
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x01000193ul;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct fnv1a_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string_view const& s ) const
|
||||
{
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x00000100000001B3ull;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits >
|
||||
{
|
||||
using is_avalanching = void;
|
||||
};
|
||||
|
||||
template<class K, class V> using std_unordered_map_fnv1a =
|
||||
std::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map_fnv1a =
|
||||
boost::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map_fnv1a =
|
||||
boost::unordered_node_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map_fnv1a =
|
||||
boost::unordered_flat_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map_fnv1a =
|
||||
absl::node_hash_map<K, V, fnv1a_hash, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map_fnv1a =
|
||||
absl::flat_hash_map<K, V, fnv1a_hash, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map_fnv1a =
|
||||
ankerl::unordered_dense::map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
int main()
|
||||
{
|
||||
init_indices();
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
|
||||
test<boost_unordered_map_fnv1a>( "boost::unordered_map, FNV-1a" );
|
||||
test<boost_unordered_node_map_fnv1a>( "boost::unordered_node_map, FNV-1a" );
|
||||
test<boost_unordered_flat_map_fnv1a>( "boost::unordered_flat_map, FNV-1a" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map_fnv1a>( "ankerl::unordered_dense::map, FNV-1a" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map_fnv1a>( "absl::node_hash_map, FNV-1a" );
|
||||
test<absl_flat_hash_map_fnv1a>( "absl::flat_hash_map, FNV-1a" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 38 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -0,0 +1,352 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::uint32_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
constexpr unsigned N = 2'000'000;
|
||||
constexpr int K = 10;
|
||||
|
||||
static std::vector< std::uint32_t > indices1, indices2, indices3;
|
||||
|
||||
static void init_indices()
|
||||
{
|
||||
indices1.push_back( 0 );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices1.push_back( i );
|
||||
}
|
||||
|
||||
indices2.push_back( 0 );
|
||||
|
||||
{
|
||||
boost::detail::splitmix64 rng;
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices2.push_back( static_cast<std::uint32_t>( rng() ) );
|
||||
}
|
||||
}
|
||||
|
||||
indices3.push_back( 0 );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices3.push_back( boost::endian::endian_reverse( static_cast<std::uint32_t>( i ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices1[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices2[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Random insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices3[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed insert", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::uint32_t s;
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices1[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices2[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Random lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices3[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed lookup", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
auto it = map.begin();
|
||||
|
||||
while( it != map.end() )
|
||||
{
|
||||
if( it->second & 1 )
|
||||
{
|
||||
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
|
||||
{
|
||||
map.erase( it++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
it = map.erase( it );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and erase odd elements", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices1[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices2[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Random erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices3[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed erase", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<std::uint32_t, std::uint32_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_insert( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_lookup( map, t1 );
|
||||
test_iteration( map, t1 );
|
||||
test_lookup( map, t1 );
|
||||
test_erase( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
init_indices();
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 30 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -0,0 +1,362 @@
|
||||
// Copyright 2021 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::uint64_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
constexpr unsigned N = 2'000'000;
|
||||
constexpr int K = 10;
|
||||
|
||||
static std::vector< std::uint64_t > indices1, indices2, indices3;
|
||||
|
||||
static void init_indices()
|
||||
{
|
||||
indices1.push_back( 0 );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices1.push_back( i );
|
||||
}
|
||||
|
||||
indices2.push_back( 0 );
|
||||
|
||||
{
|
||||
boost::detail::splitmix64 rng;
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices2.push_back( rng() );
|
||||
}
|
||||
}
|
||||
|
||||
indices3.push_back( 0 );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices3.push_back( boost::endian::endian_reverse( static_cast<std::uint64_t>( i ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices1[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices2[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Random insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices3[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed insert", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::uint64_t s;
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices1[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices2[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Random lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices3[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed lookup", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
auto it = map.begin();
|
||||
|
||||
while( it != map.end() )
|
||||
{
|
||||
if( it->second & 1 )
|
||||
{
|
||||
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
|
||||
{
|
||||
map.erase( it++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
it = map.erase( it );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and erase odd elements", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices1[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices2[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Random erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices3[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed erase", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<std::uint64_t, std::uint64_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_insert( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_lookup( map, t1 );
|
||||
test_iteration( map, t1 );
|
||||
test_lookup( map, t1 );
|
||||
test_erase( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
init_indices();
|
||||
|
||||
#if defined(BOOST_LIBSTDCXX_VERSION) && __SIZE_WIDTH__ == 32
|
||||
|
||||
// Pathological behavior:
|
||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104945
|
||||
|
||||
#else
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
|
||||
#endif
|
||||
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 30 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -0,0 +1,403 @@
|
||||
// Copyright 2021, 2022 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <boost/core/detail/splitmix64.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::uint64_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
constexpr unsigned N = 2'000'000;
|
||||
constexpr int K = 10;
|
||||
|
||||
struct uuid
|
||||
{
|
||||
unsigned char data[ 16 ];
|
||||
|
||||
uuid(): data()
|
||||
{
|
||||
}
|
||||
|
||||
uuid( std::uint64_t low, std::uint64_t high ) noexcept
|
||||
{
|
||||
boost::endian::store_little_u64( data + 0, low );
|
||||
boost::endian::store_little_u64( data + 8, high );
|
||||
}
|
||||
|
||||
inline friend std::size_t hash_value( uuid const& u ) noexcept
|
||||
{
|
||||
std::uint64_t low = boost::endian::load_little_u64( u.data + 0 );
|
||||
std::uint64_t high = boost::endian::load_little_u64( u.data + 8 );
|
||||
|
||||
std::size_t r = 0;
|
||||
|
||||
boost::hash_combine( r, low );
|
||||
boost::hash_combine( r, high );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline friend bool operator==( uuid const& u1, uuid const& u2 ) noexcept
|
||||
{
|
||||
return std::memcmp( u1.data, u2.data, 16 ) == 0;
|
||||
}
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<> struct hash< ::uuid >
|
||||
{
|
||||
std::size_t operator()( uuid const& u ) const noexcept
|
||||
{
|
||||
return hash_value( u );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
static std::vector< uuid > indices1, indices2, indices3;
|
||||
|
||||
static void init_indices()
|
||||
{
|
||||
indices1.push_back( {} );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices1.push_back( { i, 0 } );
|
||||
}
|
||||
|
||||
indices2.push_back( {} );
|
||||
|
||||
{
|
||||
boost::detail::splitmix64 rng;
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
indices2.push_back( { rng(), rng() } );
|
||||
}
|
||||
}
|
||||
|
||||
indices3.push_back( {} );
|
||||
|
||||
for( unsigned i = 1; i <= N*2; ++i )
|
||||
{
|
||||
uuid k( i, 0 );
|
||||
std::reverse( k.data + 0, k.data + 16 );
|
||||
|
||||
indices3.push_back( k );
|
||||
}
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_insert( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices1[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices2[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Random insert", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.insert( { indices3[ i ], i } );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed insert", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_lookup( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::uint64_t s;
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices1[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices2[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Random lookup", s, map.size() );
|
||||
|
||||
s = 0;
|
||||
|
||||
for( int j = 0; j < K; ++j )
|
||||
{
|
||||
for( unsigned i = 1; i <= N * 2; ++i )
|
||||
{
|
||||
auto it = map.find( indices3[ i ] );
|
||||
if( it != map.end() ) s += it->second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed lookup", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
auto it = map.begin();
|
||||
|
||||
while( it != map.end() )
|
||||
{
|
||||
if( it->second & 1 )
|
||||
{
|
||||
if constexpr( std::is_void_v< decltype( map.erase( it ) ) > )
|
||||
{
|
||||
map.erase( it++ );
|
||||
}
|
||||
else
|
||||
{
|
||||
it = map.erase( it );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and erase odd elements", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_erase( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices1[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices2[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Random erase", 0, map.size() );
|
||||
|
||||
for( unsigned i = 1; i <= N; ++i )
|
||||
{
|
||||
map.erase( indices3[ i ] );
|
||||
}
|
||||
|
||||
print_time( t1, "Consecutive reversed erase", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<uuid, std::uint64_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_insert( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_lookup( map, t1 );
|
||||
test_iteration( map, t1 );
|
||||
test_lookup( map, t1 );
|
||||
test_erase( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
init_indices();
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 30 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -0,0 +1,386 @@
|
||||
// Copyright 2021, 2022 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::size_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
static std::vector<std::string> words;
|
||||
|
||||
static void init_words()
|
||||
{
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
|
||||
char const* fn = "enwik9"; // http://mattmahoney.net/dc/textdata
|
||||
|
||||
#else
|
||||
|
||||
char const* fn = "enwik8"; // ditto
|
||||
|
||||
#endif
|
||||
|
||||
auto t1 = std::chrono::steady_clock::now();
|
||||
|
||||
std::ifstream is( fn );
|
||||
std::string in( std::istreambuf_iterator<char>( is ), std::istreambuf_iterator<char>{} );
|
||||
|
||||
boost::regex re( "[a-zA-Z]+");
|
||||
boost::sregex_token_iterator it( in.begin(), in.end(), re, 0 ), end;
|
||||
|
||||
words.assign( it, end );
|
||||
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << fn << ": " << words.size() << " words, " << ( t2 - t1 ) / 1ms << " ms\n\n";
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_word_count( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::size_t s = 0;
|
||||
|
||||
for( auto const& word: words )
|
||||
{
|
||||
++map[ word ];
|
||||
++s;
|
||||
}
|
||||
|
||||
print_time( t1, "Word count", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_contains( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::size_t s = 0;
|
||||
|
||||
for( auto const& word: words )
|
||||
{
|
||||
std::string_view w2( word );
|
||||
w2.remove_prefix( 1 );
|
||||
|
||||
s += map.contains( w2 );
|
||||
}
|
||||
|
||||
print_time( t1, "Contains", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_count( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::size_t s = 0;
|
||||
|
||||
for( auto const& word: words )
|
||||
{
|
||||
std::string_view w2( word );
|
||||
w2.remove_prefix( 1 );
|
||||
|
||||
s += map.count( w2 );
|
||||
}
|
||||
|
||||
print_time( t1, "Count", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::size_t max = 0;
|
||||
std::string_view word;
|
||||
|
||||
for( auto const& x: map )
|
||||
{
|
||||
if( x.second > max )
|
||||
{
|
||||
word = x.first;
|
||||
max = x.second;
|
||||
}
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and find max element", max, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<std::string_view, std::size_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_word_count( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_contains( map, t1 );
|
||||
test_count( map, t1 );
|
||||
test_iteration( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
// fnv1a_hash
|
||||
|
||||
template<int Bits> struct fnv1a_hash_impl;
|
||||
|
||||
template<> struct fnv1a_hash_impl<32>
|
||||
{
|
||||
std::size_t operator()( std::string_view const& s ) const
|
||||
{
|
||||
std::size_t h = 0x811C9DC5u;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x01000193ul;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct fnv1a_hash_impl<64>
|
||||
{
|
||||
std::size_t operator()( std::string_view const& s ) const
|
||||
{
|
||||
std::size_t h = 0xCBF29CE484222325ull;
|
||||
|
||||
char const * first = s.data();
|
||||
char const * last = first + s.size();
|
||||
|
||||
for( ; first != last; ++first )
|
||||
{
|
||||
h ^= static_cast<unsigned char>( *first );
|
||||
h *= 0x00000100000001B3ull;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
struct fnv1a_hash: fnv1a_hash_impl< std::numeric_limits<std::size_t>::digits >
|
||||
{
|
||||
using is_avalanching = void;
|
||||
};
|
||||
|
||||
template<class K, class V> using std_unordered_map_fnv1a =
|
||||
std::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map_fnv1a =
|
||||
boost::unordered_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map_fnv1a =
|
||||
boost::unordered_node_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map_fnv1a =
|
||||
boost::unordered_flat_map<K, V, fnv1a_hash, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map_fnv1a =
|
||||
absl::node_hash_map<K, V, fnv1a_hash, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map_fnv1a =
|
||||
absl::flat_hash_map<K, V, fnv1a_hash, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map_fnv1a =
|
||||
ankerl::unordered_dense::map<K, V, fnv1a_hash, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
int main()
|
||||
{
|
||||
init_words();
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
test<std_unordered_map_fnv1a>( "std::unordered_map, FNV-1a" );
|
||||
test<boost_unordered_map_fnv1a>( "boost::unordered_map, FNV-1a" );
|
||||
test<boost_unordered_node_map_fnv1a>( "boost::unordered_node_map, FNV-1a" );
|
||||
test<boost_unordered_flat_map_fnv1a>( "boost::unordered_flat_map, FNV-1a" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map_fnv1a>( "ankerl::unordered_dense::map, FNV-1a" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map_fnv1a>( "absl::node_hash_map, FNV-1a" );
|
||||
test<absl_flat_hash_map_fnv1a>( "absl::flat_hash_map, FNV-1a" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 38 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -0,0 +1,244 @@
|
||||
// Copyright 2021, 2022 Peter Dimov.
|
||||
// Copyright 2023 Joaquin M Lopez Munoz.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// https://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING
|
||||
#define _SILENCE_CXX20_CISO646_REMOVED_WARNING
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered/unordered_node_map.hpp>
|
||||
#include <boost/unordered/unordered_flat_map.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/node_hash_map.h"
|
||||
# include "absl/container/flat_hash_map.h"
|
||||
#endif
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
# include "ankerl/unordered_dense.h"
|
||||
#endif
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static void print_time( std::chrono::steady_clock::time_point & t1, char const* label, std::size_t s, std::size_t size )
|
||||
{
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << label << ": " << ( t2 - t1 ) / 1ms << " ms (s=" << s << ", size=" << size << ")\n";
|
||||
|
||||
t1 = t2;
|
||||
}
|
||||
|
||||
static std::vector<std::string> words;
|
||||
|
||||
static void init_words()
|
||||
{
|
||||
#if SIZE_MAX > UINT32_MAX
|
||||
|
||||
char const* fn = "enwik9"; // http://mattmahoney.net/dc/textdata
|
||||
|
||||
#else
|
||||
|
||||
char const* fn = "enwik8"; // ditto
|
||||
|
||||
#endif
|
||||
|
||||
auto t1 = std::chrono::steady_clock::now();
|
||||
|
||||
std::ifstream is( fn );
|
||||
std::string in( std::istreambuf_iterator<char>( is ), std::istreambuf_iterator<char>{} );
|
||||
|
||||
boost::regex re( "[a-zA-Z]+");
|
||||
boost::sregex_token_iterator it( in.begin(), in.end(), re, 0 ), end;
|
||||
|
||||
words.assign( it, end );
|
||||
|
||||
auto t2 = std::chrono::steady_clock::now();
|
||||
|
||||
std::cout << fn << ": " << words.size() << " words, " << ( t2 - t1 ) / 1ms << " ms\n\n";
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_word_size( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
for( auto const& word: words )
|
||||
{
|
||||
++map[ word.size() ];
|
||||
}
|
||||
|
||||
print_time( t1, "Word size count", 0, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template<class Map> BOOST_NOINLINE void test_iteration( Map& map, std::chrono::steady_clock::time_point & t1 )
|
||||
{
|
||||
std::size_t s = 0;
|
||||
|
||||
for( auto const& x: map )
|
||||
{
|
||||
s += x.second;
|
||||
}
|
||||
|
||||
print_time( t1, "Iterate and sum counts", s, map.size() );
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// counting allocator
|
||||
|
||||
static std::size_t s_alloc_bytes = 0;
|
||||
static std::size_t s_alloc_count = 0;
|
||||
|
||||
template<class T> struct allocator
|
||||
{
|
||||
using value_type = T;
|
||||
|
||||
allocator() = default;
|
||||
|
||||
template<class U> allocator( allocator<U> const & ) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
template<class U> bool operator==( allocator<U> const & ) const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class U> bool operator!=( allocator<U> const& ) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
T* allocate( std::size_t n ) const
|
||||
{
|
||||
s_alloc_bytes += n * sizeof(T);
|
||||
s_alloc_count++;
|
||||
|
||||
return std::allocator<T>().allocate( n );
|
||||
}
|
||||
|
||||
void deallocate( T* p, std::size_t n ) const noexcept
|
||||
{
|
||||
s_alloc_bytes -= n * sizeof(T);
|
||||
s_alloc_count--;
|
||||
|
||||
std::allocator<T>().deallocate( p, n );
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
struct record
|
||||
{
|
||||
std::string label_;
|
||||
long long time_;
|
||||
std::size_t bytes_;
|
||||
std::size_t count_;
|
||||
};
|
||||
|
||||
static std::vector<record> times;
|
||||
|
||||
template<template<class...> class Map> BOOST_NOINLINE void test( char const* label )
|
||||
{
|
||||
std::cout << label << ":\n\n";
|
||||
|
||||
s_alloc_bytes = 0;
|
||||
s_alloc_count = 0;
|
||||
|
||||
Map<std::size_t, std::size_t> map;
|
||||
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
auto t1 = t0;
|
||||
|
||||
test_word_size( map, t1 );
|
||||
|
||||
std::cout << "Memory: " << s_alloc_bytes << " bytes in " << s_alloc_count << " allocations\n\n";
|
||||
|
||||
record rec = { label, 0, s_alloc_bytes, s_alloc_count };
|
||||
|
||||
test_iteration( map, t1 );
|
||||
|
||||
auto tN = std::chrono::steady_clock::now();
|
||||
std::cout << "Total: " << ( tN - t0 ) / 1ms << " ms\n\n";
|
||||
|
||||
rec.time_ = ( tN - t0 ) / 1ms;
|
||||
times.push_back( rec );
|
||||
}
|
||||
|
||||
// aliases using the counting allocator
|
||||
|
||||
template<class K, class V> using allocator_for = ::allocator< std::pair<K const, V> >;
|
||||
|
||||
template<class K, class V> using std_unordered_map =
|
||||
std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_map =
|
||||
boost::unordered_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_node_map =
|
||||
boost::unordered_node_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using boost_unordered_flat_map =
|
||||
boost::unordered_flat_map<K, V, boost::hash<K>, std::equal_to<K>, allocator_for<K, V>>;
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
template<class K, class V> using absl_node_hash_map =
|
||||
absl::node_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
template<class K, class V> using absl_flat_hash_map =
|
||||
absl::flat_hash_map<K, V, absl::container_internal::hash_default_hash<K>, absl::container_internal::hash_default_eq<K>, allocator_for<K, V>>;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
template<class K, class V> using ankerl_unordered_dense_map =
|
||||
ankerl::unordered_dense::map<K, V, ankerl::unordered_dense::hash<K>, std::equal_to<K>, ::allocator< std::pair<K, V> >>;
|
||||
|
||||
#endif
|
||||
|
||||
int main()
|
||||
{
|
||||
init_words();
|
||||
|
||||
test<std_unordered_map>( "std::unordered_map" );
|
||||
test<boost_unordered_map>( "boost::unordered_map" );
|
||||
test<boost_unordered_node_map>( "boost::unordered_node_map" );
|
||||
test<boost_unordered_flat_map>( "boost::unordered_flat_map" );
|
||||
|
||||
#ifdef HAVE_ANKERL_UNORDERED_DENSE
|
||||
|
||||
test<ankerl_unordered_dense_map>( "ankerl::unordered_dense::map" );
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
|
||||
test<absl_node_hash_map>( "absl::node_hash_map" );
|
||||
test<absl_flat_hash_map>( "absl::flat_hash_map" );
|
||||
|
||||
#endif
|
||||
|
||||
std::cout << "---\n\n";
|
||||
|
||||
for( auto const& x: times )
|
||||
{
|
||||
std::cout << std::setw( 30 ) << ( x.label_ + ": " ) << std::setw( 5 ) << x.time_ << " ms, " << std::setw( 9 ) << x.bytes_ << " bytes in " << x.count_ << " allocations\n";
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ABSEIL
|
||||
# include "absl/container/internal/raw_hash_set.cc"
|
||||
# include "absl/hash/internal/hash.cc"
|
||||
# include "absl/hash/internal/low_level_hash.cc"
|
||||
# include "absl/hash/internal/city.cc"
|
||||
#endif
|
||||
@@ -1,56 +1,21 @@
|
||||
|
||||
# Copyright 2005 Daniel James.
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
path-constant images_location : ../ ;
|
||||
path-constant admonishment_location : ../../../../doc/src/images ;
|
||||
import asciidoctor ;
|
||||
|
||||
xml unordered : unordered.qbk ;
|
||||
boostbook standalone : unordered :
|
||||
<xsl:param>chunk.first.sections=1
|
||||
<xsl:param>chunk.section.depth=2
|
||||
<xsl:param>generate.section.toc.level=2
|
||||
<xsl:param>toc.section.depth=1
|
||||
<xsl:param>toc.max.depth=1
|
||||
html unordered.html : unordered.adoc ;
|
||||
|
||||
<xsl:param>boost.compact.typedef=0
|
||||
<xsl:param>boost.compact.function=0
|
||||
<xsl:param>boost.compact.enum=0
|
||||
install html_ : unordered.html : <location>html ;
|
||||
|
||||
# HTML Options:
|
||||
pdf unordered.pdf : unordered.adoc ;
|
||||
explicit unordered.pdf ;
|
||||
|
||||
<format>html:<xsl:param>boost.root=../../../..
|
||||
<format>html:<xsl:param>img.src.path=../../../../doc/html/
|
||||
<format>xhtml:<xsl:param>boost.root=../../../..
|
||||
<format>xhtml:<xsl:param>img.src.path=../../../../doc/html/
|
||||
|
||||
# PDF Options:
|
||||
|
||||
# TOC Generation: this is needed for FOP-0.9 and later:
|
||||
<xsl:param>fop1.extensions=0
|
||||
<format>pdf:<xsl:param>xep.extensions=1
|
||||
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
|
||||
<format>pdf:<xsl:param>fop.extensions=0
|
||||
# No indent on body text:
|
||||
<format>pdf:<xsl:param>body.start.indent=0pt
|
||||
# Margin size:
|
||||
<format>pdf:<xsl:param>page.margin.inner=0.5in
|
||||
# Margin size:
|
||||
<format>pdf:<xsl:param>page.margin.outer=0.5in
|
||||
# Paper type = A4
|
||||
<format>pdf:<xsl:param>paper.type=A4
|
||||
# Yes, we want graphics for admonishments:
|
||||
<xsl:param>admon.graphics=1
|
||||
# Set this one for PDF generation *only*:
|
||||
# default png graphics are awful in PDF form,
|
||||
# better use SVG's instead:
|
||||
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
|
||||
<format>pdf:<xsl:param>use.role.for.mediaobject=1
|
||||
<format>pdf:<xsl:param>preferred.mediaobject.role=print
|
||||
<format>pdf:<xsl:param>img.src.path=$(images_location)/
|
||||
#<format>pdf:<xsl:param>admon.graphics.path=$(admonishment_location)
|
||||
<format>pdf:<xsl:param>draft.mode="no"
|
||||
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/unordered/doc/html
|
||||
;
|
||||
install pdf_ : unordered.pdf : <location>pdf ;
|
||||
explicit pdf_ ;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : html_ ;
|
||||
explicit boostrelease ;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<!--
|
||||
Copyright Daniel James 2008-2009
|
||||
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
-->
|
||||
<section id="unordered.bibliography">
|
||||
<title>Bibliography</title>
|
||||
<bibliography>
|
||||
<biblioentry>
|
||||
<biblioset relation="journal">
|
||||
<title>C/C++ Users Journal</title>
|
||||
<date>February, 2006</date>
|
||||
</biblioset>
|
||||
<biblioset relation="article">
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Pete</firstname>
|
||||
<surname>Becker</surname>
|
||||
</author>
|
||||
</authorgroup>
|
||||
<title><ulink url="http://www.ddj.com/cpp/184402066">STL and TR1: Part III - Unordered containers</ulink></title>
|
||||
</biblioset>
|
||||
<para>An introducation to the standard unordered containers.</para>
|
||||
</biblioentry>
|
||||
</bibliography>
|
||||
</section>
|
||||
@@ -1,171 +0,0 @@
|
||||
[/ Copyright 2006-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:buckets The Data Structure]
|
||||
|
||||
The containers are made up of a number of 'buckets', each of which can contain
|
||||
any number of elements. For example, the following diagram shows an [classref
|
||||
boost::unordered_set unordered_set] with 7 buckets containing 5 elements, `A`,
|
||||
`B`, `C`, `D` and `E` (this is just for illustration, containers will typically
|
||||
have more buckets).
|
||||
|
||||
[diagram buckets]
|
||||
|
||||
In order to decide which bucket to place an element in, the container applies
|
||||
the hash function, `Hash`, to the element's key (for `unordered_set` and
|
||||
`unordered_multiset` the key is the whole element, but is referred to as the key
|
||||
so that the same terminology can be used for sets and maps). This returns a
|
||||
value of type `std::size_t`. `std::size_t` has a much greater range of values
|
||||
then the number of buckets, so that container applies another transformation to
|
||||
that value to choose a bucket to place the element in.
|
||||
|
||||
Retrieving the elements for a given key is simple. The same process is applied
|
||||
to the key to find the correct bucket. Then the key is compared with the
|
||||
elements in the bucket to find any elements that match (using the equality
|
||||
predicate `Pred`). If the hash function has worked well the elements will be
|
||||
evenly distributed amongst the buckets so only a small number of elements will
|
||||
need to be examined.
|
||||
|
||||
There is [link unordered.hash_equality more information on hash functions and
|
||||
equality predicates in the next section].
|
||||
|
||||
You can see in the diagram that `A` & `D` have been placed in the same bucket.
|
||||
When looking for elements in this bucket up to 2 comparisons are made, making
|
||||
the search slower. This is known as a collision. To keep things fast we try to
|
||||
keep collisions to a minimum.
|
||||
|
||||
'''
|
||||
<table frame="all"><title>Methods for Accessing Buckets</title>
|
||||
<tgroup cols="2">
|
||||
<thead><row>
|
||||
<entry><para>Method</para></entry>
|
||||
<entry><para>Description</para></entry>
|
||||
</row></thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>'''`size_type bucket_count() const`'''</entry>
|
||||
<entry>'''The number of buckets.'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`size_type max_bucket_count() const`'''</entry>
|
||||
<entry>'''An upper bound on the number of buckets.'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`size_type bucket_size(size_type n) const`'''</entry>
|
||||
<entry>'''The number of elements in bucket `n`.'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`size_type bucket(key_type const& k) const`'''</entry>
|
||||
<entry>'''Returns the index of the bucket which would contain k'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`local_iterator begin(size_type n);`'''</entry>
|
||||
<entry morerows='5'>'''Return begin and end iterators for bucket `n`.'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`local_iterator end(size_type n);`'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`const_local_iterator begin(size_type n) const;`'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`const_local_iterator end(size_type n) const;`'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`const_local_iterator cbegin(size_type n) const;`'''</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>'''`const_local_iterator cend(size_type n) const;`'''</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
'''
|
||||
|
||||
[h2 Controlling the number of buckets]
|
||||
|
||||
As more elements are added to an unordered associative container, the number
|
||||
of elements in the buckets will increase causing performance to degrade.
|
||||
To combat this the containers increase the bucket count as elements are inserted.
|
||||
You can also tell the container to change the bucket count (if required) by
|
||||
calling `rehash`.
|
||||
|
||||
The standard leaves a lot of freedom to the implementer to decide how the
|
||||
number of buckets are chosen, but it does make some requirements based on the
|
||||
container's 'load factor', the average number of elements per bucket.
|
||||
Containers also have a 'maximum load factor' which they should try to keep the
|
||||
load factor below.
|
||||
|
||||
You can't control the bucket count directly but there are two ways to
|
||||
influence it:
|
||||
|
||||
* Specify the minimum number of buckets when constructing a container or
|
||||
when calling `rehash`.
|
||||
* Suggest a maximum load factor by calling `max_load_factor`.
|
||||
|
||||
`max_load_factor` doesn't let you set the maximum load factor yourself, it just
|
||||
lets you give a /hint/. And even then, the draft standard doesn't actually
|
||||
require the container to pay much attention to this value. The only time the
|
||||
load factor is /required/ to be less than the maximum is following a call to
|
||||
`rehash`. But most implementations will try to keep the number of elements
|
||||
below the max load factor, and set the maximum load factor to be the same as
|
||||
or close to the hint - unless your hint is unreasonably small or large.
|
||||
|
||||
[table Methods for Controlling Bucket Size
|
||||
[[Method] [Description]]
|
||||
|
||||
[
|
||||
[`X(size_type n)`]
|
||||
[Construct an empty container with at least `n` buckets (`X` is the container type).]
|
||||
]
|
||||
[
|
||||
[`X(InputIterator i, InputIterator j, size_type n)`]
|
||||
[Construct an empty container with at least `n` buckets and insert elements
|
||||
from the range \[`i`, `j`) (`X` is the container type).]
|
||||
]
|
||||
[
|
||||
[`float load_factor() const`]
|
||||
[The average number of elements per bucket.]
|
||||
]
|
||||
[
|
||||
[`float max_load_factor() const`]
|
||||
[Returns the current maximum load factor.]
|
||||
]
|
||||
[
|
||||
[`float max_load_factor(float z)`]
|
||||
[Changes the container's maximum load factor, using `z` as a hint.]
|
||||
]
|
||||
[
|
||||
[`void rehash(size_type n)`]
|
||||
[Changes the number of buckets so that there at least n buckets, and
|
||||
so that the load factor is less than the maximum load factor.]
|
||||
]
|
||||
|
||||
]
|
||||
|
||||
[h2 Iterator Invalidation]
|
||||
|
||||
It is not specified how member functions other than `rehash` affect
|
||||
the bucket count, although `insert` is only allowed to invalidate iterators
|
||||
when the insertion causes the load factor to be greater than or equal to the
|
||||
maximum load factor. For most implementations this means that insert will only
|
||||
change the number of buckets when this happens. While iterators can be
|
||||
invalidated by calls to `insert` and `rehash`, pointers and references to the
|
||||
container's elements are never invalidated.
|
||||
|
||||
In a similar manner to using `reserve` for `vector`s, it can be a good idea
|
||||
to call `rehash` before inserting a large number of elements. This will get
|
||||
the expensive rehashing out of the way and let you store iterators, safe in
|
||||
the knowledge that they won't be invalidated. If you are inserting `n`
|
||||
elements into container `x`, you could first call:
|
||||
|
||||
x.rehash((x.size() + n) / x.max_load_factor() + 1);
|
||||
|
||||
[blurb Note: `rehash`'s argument is the minimum number of buckets, not the
|
||||
number of elements, which is why the new size is divided by the maximum load factor. The
|
||||
`+ 1` guarantees there is no invalidation; without it, reallocation could occur
|
||||
if the number of bucket exactly divides the target size, since the container is
|
||||
allowed to rehash when the load factor is equal to the maximum load factor.]
|
||||
|
||||
[endsect]
|
||||
@@ -1,137 +0,0 @@
|
||||
|
||||
[/ Copyright 2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:changes Change Log]
|
||||
|
||||
[h2 Review Version]
|
||||
|
||||
Initial review version, for the review conducted from 7th December 2007 to
|
||||
16th December 2007.
|
||||
|
||||
[h2 1.35.0 Add-on - 31st March 2008]
|
||||
|
||||
Unofficial release uploaded to vault, to be used with Boost 1.35.0. Incorporated
|
||||
many of the suggestions from the review.
|
||||
|
||||
* Improved portability thanks to Boost regression testing.
|
||||
* Fix lots of typos, and clearer text in the documentation.
|
||||
* Fix floating point to `std::size_t` conversion when calculating sizes from
|
||||
the max load factor, and use `double` in the calculation for greater accuracy.
|
||||
* Fix some errors in the examples.
|
||||
|
||||
[h2 Boost 1.36.0]
|
||||
|
||||
First official release.
|
||||
|
||||
* Rearrange the internals.
|
||||
* Move semantics - full support when rvalue references are available, emulated
|
||||
using a cut down version of the Adobe move library when they are not.
|
||||
* Emplace support when rvalue references and variadic template are available.
|
||||
* More efficient node allocation when rvalue references and variadic template
|
||||
are available.
|
||||
* Added equality operators.
|
||||
|
||||
[h2 Boost 1.37.0]
|
||||
|
||||
* Rename overload of `emplace` with hint, to `emplace_hint` as specified in
|
||||
[@http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2691.pdf n2691].
|
||||
* Provide forwarding headers at `<boost/unordered/unordered_map_fwd.hpp>` and
|
||||
`<boost/unordered/unordered_set_fwd.hpp>`.
|
||||
* Move all the implementation inside `boost/unordered`, to assist
|
||||
modularization and hopefully make it easier to track changes in subversion.
|
||||
|
||||
[h2 Boost 1.38.0]
|
||||
|
||||
* Use [@boost:/libs/utility/swap.html `boost::swap`].
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2237 Ticket 2237]:
|
||||
Document that the equality and inequality operators are undefined for two
|
||||
objects if their equality predicates aren't equivalent. Thanks to Daniel
|
||||
Krügler.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/1710 Ticket 1710]:
|
||||
Use a larger prime number list. Thanks to Thorsten Ottosen and Hervé
|
||||
Brönnimann.
|
||||
* Use
|
||||
[@boost:/libs/type_traits/doc/html/boost_typetraits/category/alignment.html
|
||||
aligned storage] to store the types. This changes the way the allocator is
|
||||
used to construct nodes. It used to construct the node with two calls to
|
||||
the allocator's `construct` method - once for the pointers and once for the
|
||||
value. It now constructs the node with a single call to construct and
|
||||
then constructs the value using in place construction.
|
||||
* Add support for C++0x initializer lists where they're available (currently
|
||||
only g++ 4.4 in C++0x mode).
|
||||
|
||||
[h2 Boost 1.39.0]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2756 Ticket 2756]: Avoid a warning
|
||||
on Visual C++ 2009.
|
||||
* Some other minor internal changes to the implementation, tests and
|
||||
documentation.
|
||||
* Avoid an unnecessary copy in `operator[]`.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]: Fix length of
|
||||
prime number list.
|
||||
|
||||
[h2 Boost 1.40.0]
|
||||
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2975 Ticket 2975]:
|
||||
Store the prime list as a preprocessor sequence - so that it will always get
|
||||
the length right if it changes again in the future.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/1978 Ticket 1978]:
|
||||
Implement `emplace` for all compilers.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/2908 Ticket 2908],
|
||||
[@https://svn.boost.org/trac/boost/ticket/3096 Ticket 3096]:
|
||||
Some workarounds for old versions of borland, including adding explicit
|
||||
destructors to all containers.
|
||||
* [@https://svn.boost.org/trac/boost/ticket/3082 Ticket 3082]:
|
||||
Disable incorrect Visual C++ warnings.
|
||||
* Better configuration for C++0x features when the headers aren't available.
|
||||
* Create less buckets by default.
|
||||
|
||||
[h2 Boost 1.41.0 - Major update]
|
||||
|
||||
* The original version made heavy use of macros to sidestep some of the older
|
||||
compilers' poor template support. But since I no longer support those
|
||||
compilers and the macro use was starting to become a maintenance burden it
|
||||
has been rewritten to use templates instead of macros for the implementation
|
||||
classes.
|
||||
|
||||
* The container objcet is now smaller thanks to using `boost::compressed_pair`
|
||||
for EBO and a slightly different function buffer - now using a bool instead
|
||||
of a member pointer.
|
||||
|
||||
* Buckets are allocated lazily which means that constructing an empty container
|
||||
will not allocate any memory.
|
||||
|
||||
[h2 Boost 1.42.0]
|
||||
|
||||
* Support instantiating the containers with incomplete value types.
|
||||
* Reduced the number of warnings (mostly in tests).
|
||||
* Improved codegear compatibility.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3693 Ticket 3693]:
|
||||
Add `erase_return_void` as a temporary workaround for the current
|
||||
`erase` which can be inefficient because it has to find the next
|
||||
element to return an iterator.
|
||||
* Add templated find overload for compatible keys.
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3773 Ticket 3773]:
|
||||
Add missing `std` qualifier to `ptrdiff_t`.
|
||||
* Some code formatting changes to fit almost all lines into 80 characters.
|
||||
|
||||
[h2 Boost 1.43.0]
|
||||
|
||||
* [@http://svn.boost.org/trac/boost/ticket/3966 Ticket 3966]:
|
||||
`erase_return_void` is now `quick_erase`, which is the
|
||||
[@http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#579
|
||||
current forerunner for resolving the slow erase by iterator], although
|
||||
there's a strong possibility that this may change in the future. The old
|
||||
method name remains for backwards compatibility but is considered deprecated
|
||||
and will be removed in a future release.
|
||||
* Use Boost.Exception.
|
||||
* Stop using deprecated `BOOST_HAS_*` macros.
|
||||
|
||||
[h2 Boost 1.45.0]
|
||||
|
||||
* Fix a bug when inserting into an `unordered_map` or `unordered_set` using
|
||||
iterators which returns `value_type` by copy.
|
||||
|
||||
[endsect]
|
||||
@@ -1,164 +0,0 @@
|
||||
[/ Copyright 2006-2008 Daniel James.
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ]
|
||||
|
||||
[section:comparison Comparison with Associative Containers]
|
||||
|
||||
[table Interface differences.
|
||||
[[Associative Containers] [Unordered Associative Containers]]
|
||||
|
||||
[
|
||||
[Parameterized by an ordering relation `Compare`]
|
||||
[Parameterized by a function object `Hash` and an equivalence relation
|
||||
`Pred`]
|
||||
]
|
||||
[
|
||||
[Keys can be compared using `key_compare` which is accessed by member function `key_comp()`,
|
||||
values can be compared using `value_compare` which is accessed by member function `value_comp()`.]
|
||||
[Keys can be hashed using `hasher` which is accessed by member function `hash_function()`,
|
||||
and checked for equality using `key_equal` which is accessed by member function `key_eq()`.
|
||||
There is no function object for compared or hashing values.]
|
||||
]
|
||||
[
|
||||
[Constructors have optional extra parameters for the comparison object.]
|
||||
[Constructors have optional extra parameters for the initial minimum
|
||||
number of buckets, a hash function and an equality object.]
|
||||
]
|
||||
|
||||
[
|
||||
[Keys `k1`, `k2` are considered equivalent if
|
||||
`!Compare(k1, k2) && !Compare(k2, k1)`]
|
||||
[Keys `k1`, `k2` are considered equivalent if `Pred(k1, k2)`]
|
||||
]
|
||||
[
|
||||
[Member function `lower_bound(k)` and `upper_bound(k)`]
|
||||
[No equivalent. Since the elements aren't ordered `lower_bound` and
|
||||
`upper_bound` would be meaningless.]
|
||||
]
|
||||
[
|
||||
[`equal_range(k)` returns an empty range at the position that k
|
||||
would be inserted if k isn't present in the container.]
|
||||
[`equal_range(k)` returns a range at the end of the container if
|
||||
k isn't present in the container. It can't return a positioned
|
||||
range as k could be inserted into multiple place. To find out the
|
||||
bucket that k would be inserted into use `bucket(k)`. But remember
|
||||
that an insert can cause the container to rehash - meaning that the
|
||||
element can be inserted into a different bucket.]
|
||||
]
|
||||
[
|
||||
[`iterator`, `const_iterator` are of the bidirectional category.]
|
||||
[`iterator`, `const_iterator` are of at least the forward category.]
|
||||
]
|
||||
[
|
||||
[Iterators, pointers and references to the container's elements are
|
||||
never invalidated.]
|
||||
[[link unordered.buckets.iterator_invalidation Iterators can
|
||||
be invalidated by calls to insert or rehash]. Pointers and
|
||||
references to the container's elements are never invalidated.]
|
||||
]
|
||||
[
|
||||
[Iterators iterate through the container in the order defined by
|
||||
the comparison object.]
|
||||
[Iterators iterate through the container in an arbitrary order, that
|
||||
can change as elements are inserted. Although, equivalent elements
|
||||
are always adjacent.]
|
||||
]
|
||||
[
|
||||
[No equivalent]
|
||||
[Local iterators can be used to iterate through individual buckets.
|
||||
(I don't think that the order of local iterators and iterators are
|
||||
required to have any correspondence.)]
|
||||
]
|
||||
[
|
||||
[Can be compared using the `==`, `!=`, `<`, `<=`, `>`, `>=` operators.]
|
||||
[No comparison operators are defined in the standard, although
|
||||
[link unordered.rationale.equality_operators
|
||||
implementations might extend the containers to support `==` and
|
||||
`!=`].]
|
||||
]
|
||||
[
|
||||
[]
|
||||
[When inserting with a hint, implementations are permitted to ignore
|
||||
the hint.]
|
||||
]
|
||||
[
|
||||
[`erase` never throws an exception]
|
||||
[The containers' hash or predicate function can throw exceptions
|
||||
from `erase`]
|
||||
]
|
||||
]
|
||||
|
||||
[table Complexity Guarantees
|
||||
[[Operation] [Associative Containers] [Unordered Associative Containers]]
|
||||
[
|
||||
[Construction of empty container]
|
||||
[constant]
|
||||
[O(/n/) where /n/ is the minimum number of buckets.]
|
||||
]
|
||||
[
|
||||
[Construction of container from a range of /N/ elements]
|
||||
[O(/N/ log /N/), O(/N/) if the range is sorted with `value_comp()`]
|
||||
[Average case O(/N/), worst case
|
||||
O(/N/'''<superscript>2</superscript>''')]
|
||||
]
|
||||
[
|
||||
[Insert a single element]
|
||||
[logarithmic]
|
||||
[Average case constant, worst case linear]
|
||||
]
|
||||
[
|
||||
[Insert a single element with a hint]
|
||||
[Amortized constant if t elements inserted right after hint,
|
||||
logarithmic otherwise]
|
||||
[Average case constant, worst case linear (ie. the same as
|
||||
a normal insert).]
|
||||
]
|
||||
[
|
||||
[Inserting a range of /N/ elements]
|
||||
[ /N/ log(`size()`+/N/) ]
|
||||
[Average case O(/N/), worst case O(/N/ * `size()`)]
|
||||
]
|
||||
[
|
||||
[Erase by key, `k`]
|
||||
[O(log(`size()`) + `count(k)`)]
|
||||
[Average case: O(`count(k)`), Worst case: O(`size()`)]
|
||||
]
|
||||
[
|
||||
[Erase a single element by iterator]
|
||||
[Amortized constant]
|
||||
[Average case: O(1), Worst case: O(`size()`)]
|
||||
]
|
||||
[
|
||||
[Erase a range of /N/ elements]
|
||||
[O(log(`size()`) + /N/)]
|
||||
[Average case: O(/N/), Worst case: O(`size()`)]
|
||||
]
|
||||
[
|
||||
[Clearing the container]
|
||||
[O(`size()`)]
|
||||
[O(`size()`)]
|
||||
]
|
||||
[
|
||||
[Find]
|
||||
[logarithmic]
|
||||
[Average case: O(1), Worst case: O(`size()`)]
|
||||
]
|
||||
[/ TODO: Average case is probably wrong. ]
|
||||
[
|
||||
[Count]
|
||||
[O(log(`size()`) + `count(k)`)]
|
||||
[Average case: O(1), Worst case: O(`size()`)]
|
||||
]
|
||||
[
|
||||
[`equal_range(k)`]
|
||||
[logarithmic]
|
||||
[Average case: O(`count(k)`), Worst case: O(`size()`)]
|
||||
]
|
||||
[
|
||||
[`lower_bound`,`upper_bound`]
|
||||
[logarithmic]
|
||||
[n/a]
|
||||
]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 31 KiB |