forked from boostorg/smart_ptr
		
	Compare commits
	
		
			1416 Commits
		
	
	
		
			boost-1.34
			...
			feature/qu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 82e80c7175 | ||
|  | 81318213a6 | ||
|  | 85c2a6ea74 | ||
|  | 9723621128 | ||
|  | 6dffeb8a75 | ||
|  | bee3766c04 | ||
|  | 86a873a58c | ||
|  | c808ca7ac8 | ||
|  | a4e0508ab7 | ||
|  | 1dcc441ca1 | ||
|  | cdf118b15b | ||
|  | ab75e1f892 | ||
|  | dcfb560de3 | ||
|  | 362fb1d677 | ||
|  | 79dac0e691 | ||
|  | d08d035bdf | ||
|  | 709e446968 | ||
|  | 0b0924ff82 | ||
|  | e7433ba545 | ||
|  | 785a17aaaf | ||
|  | 576d31f206 | ||
|  | 1b89a64e9b | ||
|  | 840e2ff1a8 | ||
|  | 622e2c3f83 | ||
|  | 0630607f39 | ||
|  | 316f4cef77 | ||
|  | 9e866b8a95 | ||
|  | cd01b87478 | ||
|  | b3a4c39456 | ||
|  | 5cdd3585db | ||
|  | 916c8a7d7c | ||
|  | beaf20e7b5 | ||
|  | 5e6b3a9702 | ||
|  | 63589908b5 | ||
|  | 9466e73cbe | ||
|  | b12e342c52 | ||
|  | 7f880bc205 | ||
|  | 90fd5a1fc9 | ||
|  | 0bedddbf16 | ||
|  | 173cf9ad7b | ||
|  | 9db2b96843 | ||
|  | 9b309184f8 | ||
|  | 7c87ae7985 | ||
|  | f2abcf1654 | ||
|  | 1361171bac | ||
|  | c5023afe04 | ||
|  | 7cfc326207 | ||
|  | 6b7effc83d | ||
|  | 89b4fa2552 | ||
|  | f991bdc8b3 | ||
|  | f57b455020 | ||
|  | 8b22f5cb4f | ||
|  | 1c988756d5 | ||
|  | 890b661909 | ||
|  | ab13ffa91d | ||
|  | 950ef1c130 | ||
|  | fc43a2b9d1 | ||
|  | df366326e1 | ||
|  | d77c27986e | ||
|  | dbceed6210 | ||
|  | 9ed43780e4 | ||
|  | 9026b9c556 | ||
|  | c4fed8ca7f | ||
|  | f866c6a9ae | ||
|  | 87a4dc144f | ||
|  | e6529af03f | ||
|  | b521582d46 | ||
|  | ca64f5c015 | ||
|  | 9a1d7008eb | ||
|  | 8a03c71a28 | ||
|  | 222323dc49 | ||
|  | 62fd6baa48 | ||
|  | 96ef19e72d | ||
|  | 78057574cf | ||
|  | 03e1bb314b | ||
|  | 505ed6753d | ||
|  | 82bee8581d | ||
|  | b4174f66fa | ||
|  | bf31a25fa5 | ||
|  | 06da5cd574 | ||
|  | c0c6244297 | ||
|  | b0200dd829 | ||
|  | 7f7e3748cf | ||
|  | 682b285a21 | ||
|  | 94d31304f3 | ||
|  | aa1a9ef2d7 | ||
|  | 63ac28d26f | ||
|  | 72a019944c | ||
|  | 12733a052b | ||
|  | e5472d59d1 | ||
|  | d58213cfcb | ||
|  | 38d54034d7 | ||
|  | 8863958e8d | ||
|  | 123040290c | ||
|  | abb0071ca6 | ||
|  | 000c7ae5ac | ||
|  | f11b931cfd | ||
|  | 5d8304d2cc | ||
|  | 044d1f2cb9 | ||
|  | dccecc2500 | ||
|  | 0aa32dc692 | ||
|  | b4a0629b63 | ||
|  | 38b737c490 | ||
|  | 314267a5f7 | ||
|  | ce308f21e8 | ||
|  | cd0b99380e | ||
|  | 0e6dd82e8e | ||
|  | 569b07b91c | ||
|  | bd0419c290 | ||
|  | 26cf7ff744 | ||
|  | c132c339c7 | ||
|  | 4a3432759d | ||
|  | 3832411d31 | ||
|  | 66e6f9b2ef | ||
|  | d2c2407585 | ||
|  | 694e6822ac | ||
|  | fd94706918 | ||
|  | c5e1280b77 | ||
|  | d66b173710 | ||
|  | d908c4d288 | ||
|  | 41a36f89ec | ||
|  | c1e7bd1a51 | ||
|  | 1dddd9f306 | ||
|  | e9c54b2430 | ||
|  | 17e299f11e | ||
|  | 71902a7bdb | ||
|  | e9790f99f7 | ||
|  | d4c605e6ff | ||
|  | f5152b0904 | ||
|  | 7caada352c | ||
|  | 11e56a4ad9 | ||
|  | c33504189a | ||
|  | 960741cb2e | ||
|  | c8ef3e2276 | ||
|  | 72c25383d5 | ||
|  | 6b826f1139 | ||
|  | 591d0e0728 | ||
|  | e86015f9f6 | ||
|  | 4f9487d0f3 | ||
|  | 0925dcce4e | ||
|  | 6bc7ec7e6b | ||
|  | 1650077eee | ||
|  | 635dfe46ee | ||
|  | fc0eeeffa6 | ||
|  | 4df3174d4a | ||
|  | 1a51e0f02c | ||
|  | c4ae5e0c42 | ||
|  | 85b0ab073c | ||
|  | ac9154d1e5 | ||
|  | 788313fda2 | ||
|  | 3ef8cfd02f | ||
|  | cd2aac8442 | ||
|  | 3ca07d82a7 | ||
|  | f8303629f1 | ||
|  | ef0e40bcda | ||
|  | 4af91d46f1 | ||
|  | 42dfdc9e51 | ||
|  | 763c7f56cd | ||
|  | 029f089a4a | ||
|  | 66d11714bd | ||
|  | ac0381f0b8 | ||
|  | 13be03abf8 | ||
|  | 5e7596ef06 | ||
|  | ef1651449f | ||
|  | b34786c4d4 | ||
|  | aacfb25c82 | ||
|  | c7349834be | ||
|  | 414b0a65d9 | ||
|  | bcb2566e74 | ||
|  | 7070f9b3f8 | ||
|  | 78fd14f412 | ||
|  | 861622d329 | ||
|  | 366c60ad3b | ||
|  | 331c50132b | ||
|  | 97c9204a95 | ||
|  | c577d68b02 | ||
|  | 2ce29622f5 | ||
|  | 7e9c54ffa2 | ||
|  | ca8d5216fc | ||
|  | 79e46f1719 | ||
|  | e6b5dc5ada | ||
|  | dd57aa5b70 | ||
|  | e4637b8500 | ||
|  | a0d4ec3915 | ||
|  | 59b5b17e81 | ||
|  | f2ab3b21f0 | ||
|  | e04196b6a1 | ||
|  | 95eaa2d7c3 | ||
|  | 2e31d0d633 | ||
|  | b8cb132ab4 | ||
|  | f4d7116241 | ||
|  | f2cc84a23c | ||
|  | f12a33813d | ||
|  | cfde4f7407 | ||
|  | b8d340b495 | ||
|  | 6716193d9c | ||
|  | 8f40bff2f6 | ||
|  | 1ef8f4e72d | ||
|  | f651a49d96 | ||
|  | 598314b8e1 | ||
|  | 72221d1da0 | ||
|  | 2cbeb5b185 | ||
|  | 67e657c228 | ||
|  | eba3cf92e7 | ||
|  | 8340a13539 | ||
|  | 098d0f4ce3 | ||
|  | fec5fb97c8 | ||
|  | b52d7548b3 | ||
|  | 594c7485a5 | ||
|  | d751041fb9 | ||
|  | d41546ddce | ||
|  | f3424e74e8 | ||
|  | 0eee7efd54 | ||
|  | dc2a127369 | ||
|  | 42575a0e51 | ||
|  | 64b2eac868 | ||
|  | 856ed108e8 | ||
|  | 678a544d27 | ||
|  | f1b06df6f4 | ||
|  | 620620df3d | ||
|  | 0bd61c1089 | ||
|  | d1295a9974 | ||
|  | 6e8c15c02f | ||
|  | 7c0dcd338a | ||
|  | 8d79ceaf8a | ||
|  | d35cf29b99 | ||
|  | 72ca834ae8 | ||
|  | 8afe162910 | ||
|  | 5d31c1c443 | ||
|  | 3db4ad9a15 | ||
|  | d0655ab145 | ||
|  | 7c01e640f7 | ||
|  | 00db1e02c6 | ||
|  | 914b93430a | ||
|  | 15ffd7852b | ||
|  | c66c4f5ed1 | ||
|  | 7e9d8c39a3 | ||
|  | a0d08b17e0 | ||
|  | 108a86cdbd | ||
|  | d08bdc86e5 | ||
|  | f8dcf5f6f4 | ||
|  | d38f64ded9 | ||
|  | b66fe51566 | ||
|  | 1b5568d585 | ||
|  | fad0c20263 | ||
|  | 1c61e54b13 | ||
|  | a0fc1e6daa | ||
|  | 5dd84ea389 | ||
|  | bc677e9098 | ||
|  | 688cfed63e | ||
|  | c63dc266b9 | ||
|  | 6c181a0707 | ||
|  | 4047290b85 | ||
|  | dc6c76d7e9 | ||
|  | 5a18ffdc56 | ||
|  | 09fdd5ebfd | ||
|  | 911874e139 | ||
|  | c7c0eacb74 | ||
|  | 9ed9f43ca8 | ||
|  | 0ddf990869 | ||
|  | a08a5f3d41 | ||
|  | 77c2d4cad7 | ||
|  | fd612dc114 | ||
|  | e67ebef9a7 | ||
|  | 6f5b9c7b37 | ||
|  | 91f3aa0386 | ||
|  | 686a354f21 | ||
|  | efceb04665 | ||
|  | ca57860ae2 | ||
|  | 9dcd05f918 | ||
|  | 4b724ab3f8 | ||
|  | 58915ca2fe | ||
|  | 62b0e5cdf4 | ||
|  | 951ff783b5 | ||
|  | 6421394e70 | ||
|  | 121312cc22 | ||
|  | 1e5df9d551 | ||
|  | 496127ab99 | ||
|  | 2af343a2cb | ||
|  | c6b3700ef1 | ||
|  | 2a93d30e73 | ||
|  | 02cc561248 | ||
|  | 066b398114 | ||
|  | 9c43c69c14 | ||
|  | eb8998cd91 | ||
|  | df06c324a7 | ||
|  | 0ddfab493c | ||
|  | a2732e207a | ||
|  | 5be7523ebe | ||
|  | 2320dafc03 | ||
|  | 7ab4093f46 | ||
|  | 296c203135 | ||
|  | 2dd35e5fbc | ||
|  | 977544feda | ||
|  | 54b5498208 | ||
|  | da81452f1f | ||
|  | 7b9a969215 | ||
|  | cd562eb053 | ||
|  | 91cd83e5bf | ||
|  | 2fdb8c4b0a | ||
|  | e806b53433 | ||
|  | e0c7bd9a7e | ||
|  | 766ab05a12 | ||
|  | 05cbefd28e | ||
|  | bfbdf4f45f | ||
|  | 169c0cd52a | ||
|  | 7d70691a16 | ||
|  | 90c27d7cfa | ||
|  | 43d1fe12c5 | ||
|  | a2749dddb4 | ||
|  | a71e62146c | ||
|  | 274ec17836 | ||
|  | a7341070f1 | ||
|  | a6323354cd | ||
|  | f788448101 | ||
|  | 283f2d2a11 | ||
|  | 034f94617d | ||
|  | 6a5f67b3a2 | ||
|  | dcd3c8ef80 | ||
|  | bb2a453ff6 | ||
|  | e56eec70ca | ||
|  | 60c26acab8 | ||
|  | 00f6b5dcb0 | ||
|  | 6195ae1eb0 | ||
|  | 30291c406a | ||
|  | 610f19f247 | ||
|  | 876d40a9ab | ||
|  | e4d642c46a | ||
|  | 3dffa64f58 | ||
|  | af92bd89ef | ||
|  | 4742143605 | ||
|  | 872bf10347 | ||
|  | c0ae9b3728 | ||
|  | 1298c2e8e5 | ||
|  | d593061b15 | ||
|  | 5072045f12 | ||
|  | 442e179920 | ||
|  | 9544a8cb91 | ||
|  | 5823d6bcc9 | ||
|  | f56e609757 | ||
|  | 8df63a3d0e | ||
|  | 4b6cb1223b | ||
|  | 719e819570 | ||
|  | a571b3a250 | ||
|  | f17c5e8e3b | ||
|  | e306b30dcf | ||
|  | b6b49ef591 | ||
|  | 2122c7753c | ||
|  | 7c76fb385d | ||
|  | 372fac679b | ||
|  | e3adcaed1e | ||
|  | 016e682af6 | ||
|  | 78e095d761 | ||
|  | eb8a91cb46 | ||
|  | 513cd15378 | ||
|  | 7bfa6a1f3d | ||
|  | 8120bb44cb | ||
|  | 18974ea2db | ||
|  | 2a4aca403a | ||
|  | 4d0d81477c | ||
|  | 1725e26f70 | ||
|  | 47fffaf11c | ||
|  | 7f0323a347 | ||
|  | 6d8ea0f0c4 | ||
|  | d10299159a | ||
|  | adcab0e313 | ||
|  | 4fbb9ff076 | ||
|  | 8ccb36dfcf | ||
|  | fde2e91443 | ||
|  | aa1341a6a2 | ||
|  | 053779f3ee | ||
|  | 51d8167fbf | ||
|  | 5f95fe9848 | ||
|  | 599d0bbba9 | ||
|  | f769217ca8 | ||
|  | 5d5d28a92e | ||
|  | 85fd341402 | ||
|  | eac6411867 | ||
|  | 97ef7970e8 | ||
|  | 4baa21dd5e | ||
|  | d0a89a81f0 | ||
|  | ab2b977e4a | ||
|  | f380d4466c | ||
|  | 2932ca4203 | ||
|  | 660d26c2c3 | ||
|  | a095084492 | ||
|  | a314765b94 | ||
|  | 02eba55685 | ||
|  | 9c2c991291 | ||
|  | 2e57ddb953 | ||
|  | f6c3508aee | ||
|  | b7cca00408 | ||
|  | 7e50abb9ec | ||
|  | e7360779b0 | ||
|  | 456da93897 | ||
|  | 04f0847af4 | ||
|  | 29a08cdff6 | ||
|  | 6d3af760f6 | ||
|  | a9f39d2b94 | ||
|  | 4e2f236116 | ||
|  | 4eb53db537 | ||
|  | a2b6ba85f3 | ||
|  | e37cd4154f | ||
|  | 8563fc5c4e | ||
|  | 67fab5c9ec | ||
|  | f16fbdce26 | ||
|  | c3b3835a58 | ||
|  | d1600b8abc | ||
|  | 5885763287 | ||
|  | 9bb12692b3 | ||
|  | 773ef80f5d | ||
|  | 704de2bd67 | ||
|  | 1caa233faa | ||
|  | 605d4a2789 | ||
|  | 6ab9b93088 | ||
|  | 4129bb6a5c | ||
|  | 3b64e5ecb3 | ||
|  | 4025698fe8 | ||
|  | 2d7ab197a7 | ||
|  | 5877b08490 | ||
|  | ffe5b46f75 | ||
|  | 4abc74fe28 | ||
|  | 12a646c607 | ||
|  | 937a3e0e93 | ||
|  | 258fa75a7e | ||
|  | 93d0d69f5e | ||
|  | f173f9c0fb | ||
|  | 6a5942f55f | ||
|  | 293a4ee009 | ||
|  | 8e3aa3a565 | ||
|  | 78bebd5166 | ||
|  | a47cf35b0f | ||
|  | 8d0afb670f | ||
|  | 77a35856c6 | ||
|  | 693109361e | ||
|  | 6735806863 | ||
|  | b0dc300154 | ||
|  | adc998469a | ||
|  | 4252ed31de | ||
|  | 279372a784 | ||
|  | b77b7cfd62 | ||
|  | 2553a71b79 | ||
|  | 5dfcd2a6e4 | ||
|  | 6f30b395e4 | ||
|  | 014318a1ba | ||
|  | d2c8eea08d | ||
|  | 4e0d47302b | ||
|  | 765840cd71 | ||
|  | cb4a878fa8 | ||
|  | 57a585ed46 | ||
|  | 949338ff18 | ||
|  | 50fbbe91d8 | ||
|  | e88227b506 | ||
|  | 410f2ce8d4 | ||
|  | 4e2e758f58 | ||
|  | 9cb8ee086f | ||
|  | a054a570c1 | ||
|  | 219dc523ec | ||
|  | 5da882293d | ||
|  | 868a870a59 | ||
|  | 10c6233029 | ||
|  | bcfe1be681 | ||
|  | 966786e7f9 | ||
|  | 087471a232 | ||
|  | 06bd43d5b5 | ||
|  | 1758d44e4c | ||
|  | 1c13ec0888 | ||
|  | cc7eb56f51 | ||
|  | eb64ae8daa | ||
|  | a3c8c2125a | ||
|  | 3aa419463c | ||
|  | e4ba116d7e | ||
|  | 864a0c80dd | ||
|  | be736e5088 | ||
|  | 48294c483f | ||
|  | 13e73d6a78 | ||
|  | 20a517cc3d | ||
|  | 65d412c840 | ||
|  | d031d4719f | ||
|  | c1979bcaf5 | ||
|  | 0adb1fb212 | ||
|  | 7410cb1733 | ||
|  | 2d087d0003 | ||
|  | ca7a01a593 | ||
|  | 314a6634d4 | ||
|  | 6cbc1e6775 | ||
|  | 81e1cfe301 | ||
|  | eb8aa36854 | ||
|  | e210c5728d | ||
|  | 4046186a2d | ||
|  | 01b73a8bfa | ||
|  | c85abde6b0 | ||
|  | e9523962ae | ||
|  | 4e5d067ba8 | ||
|  | 827206ec57 | ||
|  | 0cdad6421d | ||
|  | f7f7e0183d | ||
|  | f901988e57 | ||
|  | 22d150a1a9 | ||
|  | fb17bf685e | ||
|  | 052ebd1946 | ||
|  | 028bb2cee8 | ||
|  | 9fe6885078 | ||
|  | 6e5a382b6b | ||
|  | 87272703c2 | ||
|  | 1c097b5764 | ||
|  | 014181e1f9 | ||
|  | 0b9547ddad | ||
|  | b104d85d95 | ||
|  | e92d79c0a6 | ||
|  | 2b5869882a | ||
|  | 1f86907a3d | ||
|  | 685b40cc1b | ||
|  | dcfb8489c6 | ||
|  | 6218c52c1a | ||
|  | c2b6e96cd7 | ||
|  | b062d84d36 | ||
|  | 68fb786d4d | ||
|  | f7275b7f45 | ||
|  | edf02ab0f9 | ||
|  | 5b316e6e90 | ||
|  | 7ed8583a9c | ||
|  | 6474847481 | ||
|  | 75003f734f | ||
|  | 79e6fcdd61 | ||
|  | 4341446e04 | ||
|  | 9c18322e85 | ||
|  | 49095c3236 | ||
|  | fff61ab5d6 | ||
|  | aef27128f2 | ||
|  | c1d72af0a4 | ||
|  | 0e78e219f5 | ||
|  | 2e469dd7f3 | ||
|  | d9296befa8 | ||
|  | f321ce404f | ||
|  | 67d897a533 | ||
|  | e462f17c2d | ||
|  | b8390aeffb | ||
|  | 9dafc01024 | ||
|  | 7d51c868eb | ||
|  | 0b0b7af05b | ||
|  | 7bd389c95e | ||
|  | 1cae5c5696 | ||
|  | 369fdbe38d | ||
|  | 43b37d4f28 | ||
|  | a048cfb56d | ||
|  | 070a3a9f1a | ||
|  | d03ef3db5c | ||
|  | 6d97c2b89e | ||
|  | 7484d4da41 | ||
|  | 2964ed2379 | ||
|  | a7668291d2 | ||
|  | ffc48e63d8 | ||
|  | bcc9e50a54 | ||
|  | 8812114601 | ||
|  | 5b817ba04d | ||
|  | 6db55f7dfd | ||
|  | 61de342adc | ||
|  | 7f760526ab | ||
|  | 478a819cb5 | ||
|  | 902ca6fdf3 | ||
|  | 074882976f | ||
|  | c1820b4a27 | ||
|  | 8096b7d324 | ||
|  | bdcab9df47 | ||
|  | 8f99919102 | ||
|  | 27898b0823 | ||
|  | 47ee1e09e9 | ||
|  | 4dda1b5fbb | ||
|  | 585de501da | ||
|  | 420626d6d9 | ||
|  | ab99c8f7aa | ||
|  | 0eb6ad145d | ||
|  | 1d314c5668 | ||
|  | 5b7d3c08ab | ||
|  | f770e53989 | ||
|  | c4d07defcd | ||
|  | 65e616c90b | ||
|  | f90b418460 | ||
|  | bd2474e7f3 | ||
|  | a88d8b5b29 | ||
|  | 213c00aed7 | ||
|  | 52d976fde2 | ||
|  | a6031ff8e2 | ||
|  | 239fe204de | ||
|  | e75fa9329b | ||
|  | 3b16e1cc3e | ||
|  | 392b3c76f0 | ||
|  | dea4e8129d | ||
|  | 0dfb4dad0f | ||
|  | aec76051f8 | ||
|  | 8f2e6d04de | ||
|  | 8d9c4df71a | ||
|  | b18f68324f | ||
|  | aeadd6aeff | ||
|  | 3c47079f4d | ||
|  | ca9cb71e86 | ||
|  | ba98b8c33f | ||
|  | 3160cbb2e3 | ||
|  | bfa3752ad7 | ||
|  | e9010baaf5 | ||
|  | b530ffcae5 | ||
|  | 7f42d987e7 | ||
|  | 469015992a | ||
|  | 33b18c7da0 | ||
|  | 596adfc69a | ||
|  | e99e722fa5 | ||
|  | 7ef8fa4a19 | ||
|  | 9081dc5573 | ||
|  | 0043228495 | ||
|  | 6bdd3fde65 | ||
|  | 3568e093bb | ||
|  | acb29ad6f3 | ||
|  | d2c1ed0ed5 | ||
|  | 0085752a56 | ||
|  | d7ad42724d | ||
|  | 83d3f07b0d | ||
|  | 994f39f9b0 | ||
|  | f45dd4d955 | ||
|  | b4abcdb016 | ||
|  | 25cf644f60 | ||
|  | 71ef7850ab | ||
|  | 40c0ddcbd6 | ||
|  | 687d31b7c8 | ||
|  | fac6fbe3cf | ||
|  | d3b9ee7d24 | ||
|  | 650537da60 | ||
|  | 324347b9ec | ||
|  | 79e675c727 | ||
|  | 6ef791c715 | ||
|  | 15ed558a29 | ||
|  | 106ada7770 | ||
|  | 9f70f6619f | ||
|  | 494c0cd2c0 | ||
|  | 8c058dfeee | ||
|  | 0807efa91a | ||
|  | bea0fc4a37 | ||
|  | 3f21bac34f | ||
|  | 7beb91fd0e | ||
|  | d1bb87d34e | ||
|  | 7570340d70 | ||
|  | b42acf77b3 | ||
|  | 1f9c63c34f | ||
|  | f8524c42a8 | ||
|  | 52fbf70879 | ||
|  | fb59cd574e | ||
|  | c749052162 | ||
|  | 970e88897c | ||
|  | 609de5d711 | ||
|  | d641b9c436 | ||
|  | 3bb4e4d2df | ||
|  | 5ab9a77d50 | ||
|  | b80ffbeb3d | ||
|  | 5f8c2a7ee0 | ||
|  | 94634cb853 | ||
|  | 17a07a228e | ||
|  | d4bc4c9733 | ||
|  | 1d7f6b9bfd | ||
|  | d718d21d6b | ||
|  | 39b14fa0d6 | ||
|  | 19147212a9 | ||
|  | 53928bcc12 | ||
|  | 9e568dad6e | ||
|  | ebd1788f2c | ||
|  | 3e2ac10e94 | ||
|  | 61075bb9df | ||
|  | 3e61a63f60 | ||
|  | a7fbb0a841 | ||
|  | 1e9e2ed6aa | ||
|  | bdc19dee01 | ||
|  | 3aa720714d | ||
|  | 94a04e57fb | ||
|  | 776b33ec09 | ||
|  | 5595622c3e | ||
|  | 2ae3e4ba44 | ||
|  | b5498d944e | ||
|  | 8fac3c9f2f | ||
|  | a14515a364 | ||
|  | 190c06e25d | ||
|  | 62a8a9d6cc | ||
|  | 48401806f4 | ||
|  | 02de302774 | ||
|  | 80597b379e | ||
|  | 840e9fc96e | ||
|  | 70367e848e | ||
|  | e8daeaee1c | ||
|  | 3b9ae9fd5f | ||
|  | 20fedcff2c | ||
|  | de38a735ea | ||
|  | ce52fb1045 | ||
|  | 6b787f1cec | ||
|  | 2185c4f005 | ||
|  | 6d5f554baa | ||
|  | f3279d24b4 | ||
|  | c87b6e8af8 | ||
|  | aaded4f85c | ||
|  | eb1a002e34 | ||
|  | 3304a56101 | ||
|  | 181f38682f | ||
|  | 5b1a8412c3 | ||
|  | e52905cf3c | ||
|  | b7f99ceba6 | ||
|  | a7ade6f062 | ||
|  | 097d2e9bf9 | ||
|  | d44a78d671 | ||
|  | 582eb63cb3 | ||
|  | 181b449a57 | ||
|  | da8de3e95b | ||
|  | 6c27833099 | ||
|  | 83e6e00456 | ||
|  | 522f6c1869 | ||
|  | cd8de9d4a6 | ||
|  | e26542272d | ||
|  | e13beef5df | ||
|  | 8298952a12 | ||
|  | 821925c536 | ||
|  | 427124543b | ||
|  | 46f00ea993 | ||
|  | 4473bf8ec2 | ||
|  | 7a7ac4512e | ||
|  | 38b6334e36 | ||
|  | 7af503d3bb | ||
|  | 4db7219c32 | ||
|  | 3f17244225 | ||
|  | ca93749614 | ||
|  | 05d5a4e9a0 | ||
|  | 970a179ac2 | ||
|  | a06123eb87 | ||
|  | fd543d3292 | ||
|  | df90496583 | ||
|  | 20ead68473 | ||
|  | 79cde147c9 | ||
|  | abbe975e8f | ||
|  | 8ba0730686 | ||
|  | 686efe100b | ||
|  | acb880d8c2 | ||
|  | 1712b87cb6 | ||
|  | f8943703f8 | ||
|  | a42dda0af4 | ||
|  | 9b9b6d3ca6 | ||
|  | d875a68ceb | ||
|  | 8cb2c56556 | ||
|  | 290fe82a43 | ||
|  | 94824c807f | ||
|  | 334654de06 | ||
|  | 0ab0e6eecc | ||
|  | effc9f73d6 | ||
|  | 99762e7dde | ||
|  | add539142b | ||
|  | e067fd2cfd | ||
|  | 212528860a | ||
|  | 711c36958a | ||
|  | 7104e7dc7e | ||
|  | 254bda34b7 | ||
|  | 3fd53ced83 | ||
|  | 75de3dbcf1 | ||
|  | 7faec4265b | ||
|  | c81d0806e4 | ||
|  | a74329794c | ||
|  | 71756350d9 | ||
|  | f65c57d9d2 | ||
|  | b1fc261fe6 | ||
|  | aedcf3ccda | ||
|  | a1a5999a38 | ||
|  | 8afd3bee69 | ||
|  | 2a56c73924 | ||
|  | 720ce12a25 | ||
|  | 2be09db523 | ||
|  | de10be8560 | ||
|  | 7b71068b52 | ||
|  | 6b562cb5b1 | ||
|  | 3d2c230623 | ||
|  | 553c7994ba | ||
|  | 280aadfcdb | ||
|  | 59ac922a1c | ||
|  | 8de3e84021 | ||
|  | bd4f9c239a | ||
|  | 528195233b | ||
|  | 8c49f5a637 | ||
|  | 0bab2cc658 | ||
|  | 88f0a98d71 | ||
|  | 96d82e0275 | ||
|  | 40387ef654 | ||
|  | d28b0d07fc | ||
|  | 1c83d65701 | ||
|  | 1d41a328f7 | ||
|  | b1beb11a45 | ||
|  | bf3e9cc7af | ||
|  | 506239bef5 | ||
|  | d6841e6d71 | ||
|  | 56ae9f86c1 | ||
|  | 1a74757cfa | ||
|  | 07e222217b | ||
|  | 71c9165119 | ||
|  | f32669400c | ||
|  | b550e028f5 | ||
|  | ed2eaddc5d | ||
|  | d523c3423e | ||
|  | 1968d17d2f | ||
|  | e1e99c5ba3 | ||
|  | d586469d60 | ||
|  | fbb851097f | ||
|  | 75add10b1d | ||
|  | 71b2f87e35 | ||
|  | c759321782 | ||
|  | 3e625c07e8 | ||
|  | 7ff1c65494 | ||
|  | 75cab39801 | ||
|  | 38cb523713 | ||
|  | 5f1d4eae4f | ||
|  | adc0cdddff | ||
|  | dcfa031de7 | ||
|  | 8c9e8b5556 | ||
|  | d9333e5375 | ||
|  | 3d279e6c6d | ||
|  | c003fba3a0 | ||
|  | 0c29e86728 | ||
|  | 016af907bd | ||
|  | 0337743c8c | ||
|  | 208bfd78f9 | ||
|  | 2c32bf91b7 | ||
|  | b7ee788845 | ||
|  | a56378ee35 | ||
|  | 443302306e | ||
|  | f5402a937e | ||
|  | fe04bea979 | ||
|  | 8fbb5e9e7f | ||
|  | 0401afc106 | ||
|  | b69ca7aaa5 | ||
|  | dffbf7c931 | ||
|  | 5dabdf635c | ||
|  | 3dbde36076 | ||
|  | 97a9aac5f0 | ||
|  | bd5b684fd3 | ||
|  | 6ede4ec4c6 | ||
|  | aab1328e06 | ||
|  | 451c71c1bd | ||
|  | 6341b8802a | ||
|  | e274885fd2 | ||
|  | 82fe5f5095 | ||
|  | 8c50214e3f | ||
|  | 21198d07fd | ||
|  | b4c8cf3958 | ||
|  | 77aeaee7a7 | ||
|  | 677a0777d2 | ||
|  | 7c7250379b | ||
|  | 142eb95986 | ||
|  | d9f24f882e | ||
|  | 0fd3947e19 | ||
|  | 43bc30e576 | ||
|  | e0ec2a0aaa | ||
|  | 5320981cbb | ||
|  | d676bac36a | ||
|  | ec1c6ed414 | ||
|  | ce36b11fd5 | ||
|  | eee70bdcab | ||
|  | 97eed20d9b | ||
|  | 6b6b63ef37 | ||
|  | 1bdabdb96b | ||
|  | 0876e67ac7 | ||
|  | fdcb2572a3 | ||
|  | 71d99e89e9 | ||
|  | 2dc506f4bc | ||
|  | 7161dc5842 | ||
|  | ec97270c01 | ||
|  | b7a759f00f | ||
|  | 4f2392ffa5 | ||
|  | 80a06c8883 | ||
|  | d0a458616f | ||
|  | def81b1941 | ||
|  | 4f276715ce | ||
|  | a47bbfe95c | ||
|  | 90fe855f1b | ||
|  | 991436303d | ||
|  | b274ed4cc3 | ||
|  | 870a989fcf | ||
|  | 5f7a5a5912 | ||
|  | 82db88f4fa | ||
|  | c8df85434e | ||
|  | 68517b43bd | ||
|  | 72ac0e8bfd | ||
|  | 6c7578e206 | ||
|  | 3149446fe8 | ||
|  | b11d734f73 | ||
|  | 6f5f8babf4 | ||
|  | 7d7f32c3a9 | ||
|  | cb697fe9cb | ||
|  | 8422135bf2 | ||
|  | fd60899dfb | ||
|  | a11ab16010 | ||
|  | 9b9cad3f5b | ||
|  | 7ce5b6b2a9 | ||
|  | 7e3ae44bc2 | ||
|  | 57dc400fbf | ||
|  | 5f485c2952 | ||
|  | 260af64027 | ||
|  | f837c7f56c | ||
|  | 54fb49a5be | ||
|  | c23bd41c44 | ||
|  | a64cc5c41c | ||
|  | e1f170cd49 | ||
|  | 52a5c422a1 | ||
|  | d46e3c7cbd | ||
|  | 5008957bd0 | ||
|  | 6d73b4aa54 | ||
|  | 540149f019 | ||
|  | 9f5822f427 | ||
|  | d229ae870c | ||
|  | 3ac6dbbf08 | ||
|  | af5141d492 | ||
|  | 975d04ac62 | ||
|  | 90e74511f7 | ||
|  | f27b780724 | ||
|  | 51ab46a07d | ||
|  | e8595a05af | ||
|  | 154a274916 | ||
|  | 2b033ce05d | ||
|  | 63a05a3576 | ||
|  | aede0039bf | ||
|  | 72e5fb6fd7 | ||
|  | f91e7e9ce7 | ||
|  | 7fef3bb40b | ||
|  | ad658fa5ec | ||
|  | 83b3b703e0 | ||
|  | 7806737b52 | ||
|  | 87e5debdc2 | ||
|  | db78d9b2be | ||
|  | 630e4f49f3 | ||
|  | a68db557e8 | ||
|  | 4de3f36839 | ||
|  | 4e46cb0609 | ||
|  | 73153d5797 | ||
|  | d7fa365843 | ||
|  | 6e0ee30543 | ||
|  | fed15ad8c5 | ||
|  | bba3b446bd | ||
|  | 4c8a558982 | ||
|  | a41b81f1c8 | ||
|  | c103ace77a | ||
|  | 04f456f86d | ||
|  | 3a188af8d6 | ||
|  | b701ed0225 | ||
|  | 5e9bb19688 | ||
|  | a4f853bfbc | ||
|  | 832ed079b9 | ||
|  | d9b29beebe | ||
|  | 182452e057 | ||
|  | 5f69684c8f | ||
|  | 70ffd2921f | ||
|  | 00aee2c7dc | ||
|  | 85d8056368 | ||
|  | 106832df66 | ||
|  | 2549b818c5 | ||
|  | be06392771 | ||
|  | 56b0853887 | ||
|  | f5e6e4063e | ||
|  | 8767b9580e | ||
|  | 0e6ddb843e | ||
|  | 14be9eb90f | ||
|  | fa91b7d020 | ||
|  | 382fb54a52 | ||
|  | e4f24e4d3d | ||
|  | 7d1c527ac0 | ||
|  | fc20a29c99 | ||
|  | 0dc1faa6d3 | ||
|  | 7b9354fcf3 | ||
|  | a7d96b4762 | ||
|  | 6eefc6bf81 | ||
|  | 172afff6ca | ||
|  | 9355404d10 | ||
|  | d61e675caf | ||
|  | 240c66e633 | ||
|  | 6df3a0295e | ||
|  | e497aec58a | ||
|  | 2d56e85174 | ||
|  | 579b347267 | ||
|  | 82e178f043 | ||
|  | 3178d38137 | ||
|  | 46d119c385 | ||
|  | e39fcad839 | ||
|  | e5950adc43 | ||
|  | de6dc3a26e | ||
|  | 06c4dacaf2 | ||
|  | 72095a4804 | ||
|  | dcc1713c59 | ||
|  | 32a28ec462 | ||
|  | f6d5257597 | ||
|  | ef817e91d2 | ||
|  | 43b43aa83a | ||
|  | d3a549e93a | ||
|  | e8be24c003 | ||
|  | c55ffa1cab | ||
|  | 66f34142be | ||
|  | 63834f7233 | ||
|  | 049d0698b7 | ||
|  | 5ba3312519 | ||
|  | bb700870c0 | ||
|  | 6a218a5ef2 | ||
|  | e36689bd5e | ||
|  | 1c070b3a32 | ||
|  | 647f67aabf | ||
|  | c14369aac9 | ||
|  | 7ab4f6ce92 | ||
|  | bbf0245248 | ||
|  | 619b168614 | ||
|  | 4ba8d879f1 | ||
|  | c28bef2e9b | ||
|  | 5f0155cca6 | ||
|  | db542de908 | ||
|  | 5fc6fe474b | ||
|  | d42ce87557 | ||
|  | 67f5e9825e | ||
|  | fd52dbc411 | ||
|  | 6e269872df | ||
|  | ecceb710de | ||
|  | 9863467152 | ||
|  | b306c9751f | ||
|  | 6b0d96af96 | ||
|  | c03bfd0b4d | ||
|  | 8093967da7 | ||
|  | 7a4ad75f5d | ||
|  | f390d9e265 | ||
|  | ea22982865 | ||
|  | 09e77bc8df | ||
|  | b3f2ebedbc | ||
|  | 1209531fe0 | ||
|  | 6c2ed927e4 | ||
|  | 7a733263da | ||
|  | 08e5894510 | ||
|  | 3551d17566 | ||
|  | 32fe0b8f26 | ||
|  | 2d3cc0db7d | ||
|  | 188602581d | ||
|  | 88c2baa20b | ||
|  | 1adf546ddb | ||
|  | 5e5ff387fa | ||
|  | ea55019260 | ||
|  | 500913db6d | ||
|  | 19283a3548 | ||
|  | cfd4152291 | ||
|  | f5adfb0963 | ||
|  | 8597433028 | ||
|  | 4da0e2b7fc | ||
|  | 2346941b15 | ||
|  | 39ff002d2e | ||
|  | fceea2e584 | ||
|  | b17205ded7 | ||
|  | d74c09dd5a | ||
|  | 97d32745aa | ||
|  | c7b6e56b30 | ||
|  | 7835914d83 | ||
|  | 98b92fa83a | ||
|  | 392885a56a | ||
|  | b4594eab3b | ||
|  | ddfcc5f417 | ||
|  | 3f458c68f4 | ||
|  | 79b229adcd | ||
|  | 94b6487ca1 | ||
|  | cf769b94a7 | ||
|  | 215771c83d | ||
|  | 2805ae9362 | ||
|  | 7adb1cc1ec | ||
|  | da9524d637 | ||
|  | 6b2556edfb | ||
|  | cb0797acf0 | ||
|  | e8103f9774 | ||
|  | 71eb435412 | ||
|  | 4a2dad1574 | ||
|  | babc72757d | ||
|  | c19cbc1892 | ||
|  | d065e4d971 | ||
|  | 777b86a661 | ||
|  | aae5440854 | ||
|  | 227d2e3255 | ||
|  | 8bf183b373 | ||
|  | 5017da2514 | ||
|  | 3b0b10d06d | ||
|  | 25e11b20d3 | ||
|  | fa513340d7 | ||
|  | 0e90213746 | ||
|  | 980070e63f | ||
|  | 5bdde37414 | ||
|  | 2aaa913b11 | ||
|  | 58a46f4e55 | ||
|  | 8cc50a5ce9 | ||
|  | 2731957b5b | ||
|  | fe06c120b9 | ||
|  | c1f41aa925 | ||
|  | ffa3327817 | ||
|  | 999c284109 | ||
|  | d512eaaa0f | ||
|  | 730980f3ee | ||
|  | 3d50db11b9 | ||
|  | aa7562c3e5 | ||
|  | c57245d710 | ||
|  | 945c013a12 | ||
|  | df544871d7 | ||
|  | 89190ca17e | ||
|  | 5d9312239c | ||
|  | 93b5cace12 | ||
|  | e50c849ab3 | ||
|  | dbea328b8b | ||
|  | c06ba497a3 | ||
|  | 734b5d1354 | ||
|  | 0467af1b83 | ||
|  | dc5406aa5a | ||
|  | 6e873de0fa | ||
|  | 322bcd7efa | ||
|  | bb72e0a092 | ||
|  | d8eb2fc105 | ||
|  | e7d3987cfb | ||
|  | 6662ae7242 | ||
|  | 2ba7b6b99b | ||
|  | a30e291022 | ||
|  | 0b6cab9f2f | ||
|  | 8c15401ea7 | ||
|  | 03ae5cdbc6 | ||
|  | 0c22e55f3e | ||
|  | 10dcb8db7c | ||
|  | f2d4b67a48 | ||
|  | 16084637a6 | ||
|  | 3e447c919c | ||
|  | b0f72d7b3d | ||
|  | 4c98df7c57 | ||
|  | c2048732d8 | ||
|  | 5979c1d4bd | ||
|  | 1029ae0ea5 | ||
|  | 27a312228c | ||
|  | 3090f6f4af | ||
|  | 2c29f1e5a9 | ||
|  | 40073ef64f | ||
|  | b9970eda45 | ||
|  | df364f37f2 | ||
|  | 9147489b4c | ||
|  | 33ba2c4722 | ||
|  | d1348ea05e | ||
|  | faf212f4aa | ||
|  | 57a5441ebf | ||
|  | 90db9a6435 | ||
|  | 017ab7e2ee | ||
|  | 1c208ad3ea | ||
|  | 5fc9bf5bc5 | ||
|  | c846d230f0 | ||
|  | e4cb5e131f | ||
|  | fbe4ddf4a2 | ||
|  | 288fb7efcf | ||
|  | 7b097467d6 | ||
|  | 9d9e6350f2 | ||
|  | 7cb040edb0 | ||
|  | d6ac116b71 | ||
|  | 7e9664396a | ||
|  | b4b415553c | ||
|  | f76a8d95d8 | ||
|  | 8abc8889d1 | ||
|  | c5b47e2136 | ||
|  | 7c0815c567 | ||
|  | 210288f02e | ||
|  | cf7b6904e8 | ||
|  | b978919dd1 | ||
|  | 1086aff971 | ||
|  | 445e8d1728 | ||
|  | 545745d649 | ||
|  | 634866c28a | ||
|  | b18b47770d | ||
|  | 69aa01ec00 | ||
|  | e3d2f2ee6b | ||
|  | 593093e46d | ||
|  | 9196247dea | ||
|  | 53d5d086ea | ||
|  | 1426b0bbdd | ||
|  | 4fabf9b352 | ||
|  | a2fc6e12da | ||
|  | c3b51e201b | ||
|  | d71cc6ab08 | ||
|  | 825786d59a | ||
|  | 37f10d500d | ||
|  | 0d77fd0678 | ||
|  | 6ca6d3ce6f | ||
|  | cfc82854d3 | ||
|  | 3c84388186 | ||
|  | a46d405778 | ||
|  | 2e53b1eb38 | ||
|  | b9d77d877e | ||
|  | 1f50e3abe4 | ||
|  | 37c9a235a5 | ||
|  | 7083e76666 | ||
|  | 7aac2f3263 | ||
|  | 458dffdab9 | ||
|  | 697f338510 | ||
|  | f7919f0b9f | ||
|  | f4386409d9 | ||
|  | ae34be773f | ||
|  | 1b91c1dbea | ||
|  | ba349679f3 | ||
|  | 577528812a | ||
|  | e78efdbb96 | ||
|  | a3b84f8586 | ||
|  | 3824a6b156 | ||
|  | b0fd8a6b08 | ||
|  | 4f5062004a | ||
|  | f040bed751 | ||
|  | 2f8945a885 | ||
|  | 2bd0778778 | ||
|  | eec640bfd7 | ||
|  | 754fd941ee | ||
|  | b691be0af9 | ||
|  | fa597b877e | ||
|  | d0a9d76494 | ||
|  | 979e76b7e0 | ||
|  | c97eebabf7 | ||
|  | 030a848c5f | ||
|  | 18bfaea996 | ||
|  | 502de325ee | ||
|  | 9f49538b37 | ||
|  | 2ee5eb70f3 | ||
|  | 32eb028e13 | ||
|  | e824e23ec2 | ||
|  | e94f64039d | ||
|  | 63b17c24ea | ||
|  | f5cc79f58d | ||
|  | 8a421c2098 | ||
|  | 28d7e348c1 | ||
|  | 5fa1cbf6e1 | ||
|  | fc12543814 | ||
|  | 9f30442d1e | ||
|  | a4293f9dfa | ||
|  | 4b4a62513f | ||
|  | 0368a37fde | ||
|  | 28de0cb1e3 | ||
|  | 3dacec8e1d | ||
|  | a1b4fc8d95 | ||
|  | 5758e51948 | ||
|  | 287d329276 | ||
|  | d34d638998 | ||
|  | 6f2bdddfa0 | ||
|  | 9227371881 | ||
|  | e88dd9fc77 | ||
|  | 77971c6ff5 | ||
|  | 1742c37942 | ||
|  | fa3c56747d | ||
|  | fbc6919eae | ||
|  | 31e06b4a1d | ||
|  | dc3ffc5f4b | ||
|  | 0610947c4a | ||
|  | 22f1b092c9 | ||
|  | 9c55fbc6c2 | ||
|  | 5a2771e585 | ||
|  | dad59f3325 | ||
|  | bad394b1e9 | ||
|  | f93110620a | ||
|  | 6be1e3fceb | ||
|  | cf91287732 | ||
|  | 68c939ec5a | ||
|  | a378c8c278 | ||
|  | 905a3711db | ||
|  | ed32efcc51 | ||
|  | eb0ff40d62 | ||
|  | ad1b344405 | ||
|  | 0da6902267 | ||
|  | 10f6ff8b77 | ||
|  | 13f91c15f0 | ||
|  | a2c5208b8e | ||
|  | 55583ac749 | ||
|  | c40b306647 | ||
|  | d9b9921d23 | ||
|  | 6f91ea87c3 | ||
|  | ed79000ea8 | ||
|  | 6e804e64b8 | ||
|  | 395766e2d3 | ||
|  | 774332f85a | ||
|  | f5990cab65 | ||
|  | 6175baf858 | ||
|  | 2fb567b3f2 | ||
|  | 2b25579338 | ||
|  | a97cd2d0cc | ||
|  | e3b9389a24 | ||
|  | 6ba78f76f6 | ||
|  | 8c7954a53a | ||
|  | 556b9fe563 | ||
|  | 77ab953171 | ||
|  | 991b02b03e | ||
|  | 31d0c48f18 | ||
|  | 1b49f08cb8 | ||
|  | 034c12d244 | ||
|  | f884c53bd6 | ||
|  | 07b4c17980 | ||
|  | 1bc4f16ff8 | ||
|  | 774a8d330c | ||
|  | 0fd94d6d56 | ||
|  | 866590ee97 | ||
|  | 2a92df56f2 | ||
|  | a9cd84f43d | ||
|  | 366472fc35 | ||
|  | 2bfe13c9c4 | ||
|  | 83e2510ce5 | ||
|  | 31685fe551 | ||
|  | 05e050abe0 | ||
|  | d261079616 | ||
|  | d52878df88 | ||
|  | 4b0490c0ae | ||
|  | 2f1b1acc7a | ||
|  | f0f9f72be6 | ||
|  | efdc390bc9 | ||
|  | d13f1d8694 | ||
|  | 83c43617af | ||
|  | da323af72d | ||
|  | 0c4aaef77c | ||
|  | 440fcb7ba0 | ||
|  | 18a6c1add8 | ||
|  | 357d3c4d54 | ||
|  | 4bb747fb27 | ||
|  | f13591ef2b | ||
|  | e3422efec6 | ||
|  | a01e4c3f83 | ||
|  | 6f8dc5923c | ||
|  | 7dc6b3d810 | ||
|  | 2251b1d2df | ||
|  | 8b3907ae81 | ||
|  | 77f2d3f614 | ||
|  | 93545d5cf2 | ||
|  | 9e92c6354c | ||
|  | e12ed6864b | ||
|  | b541145a60 | ||
|  | ca344809ba | ||
|  | 7802c695ef | ||
|  | 71fa2cd658 | ||
|  | 04be979670 | ||
|  | 35f2af947c | ||
|  | 3a578ac7c1 | ||
|  | 9365853fde | ||
|  | 16828c9c0a | ||
|  | 2fe899cdfe | ||
|  | b45d011d5a | ||
|  | 4094c23537 | ||
|  | f85a1bf406 | ||
|  | dbd62686a3 | ||
|  | e4f638025c | ||
|  | d8296b3933 | ||
|  | b4885a1dd6 | ||
|  | 748b1baee8 | ||
|  | 4880292c07 | ||
|  | 6b25c57712 | ||
|  | 373c52efa3 | ||
|  | acb6824ef7 | ||
|  | 316d00c3fc | ||
|  | 515be965bd | ||
|  | 6ef32e1627 | ||
|  | 2452705117 | ||
|  | bb076d67e6 | ||
|  | b08789b784 | ||
|  | 5df69a8946 | ||
|  | dc6a8f0696 | ||
|  | af7d4fabad | ||
|  | d17a096407 | ||
|  | d7448b5746 | ||
|  | f22516d650 | ||
|  | b30aa1468a | ||
|  | 5b17f88f0e | ||
|  | 1c2d780f9e | ||
|  | 2eb3991630 | ||
|  | 3a4dc43924 | ||
|  | a055d9829e | ||
|  | f596092bac | ||
|  | 4ba016d29e | ||
|  | 7ca6d86bdc | ||
|  | b2a3c9e59d | ||
|  | 60ae24f4ae | ||
|  | dba6ebbb01 | ||
|  | d2194e3b24 | ||
|  | 5ab6b24856 | ||
|  | e6f6ec9fa3 | ||
|  | f854829d86 | ||
|  | 7b5beeedde | ||
|  | 9e41d1f194 | ||
|  | f49a2fb1e1 | ||
|  | 87c6b6b403 | ||
|  | 9db307eda5 | ||
|  | 5a85c1f0f2 | ||
|  | f5ce4dbc4c | ||
|  | b2354d0a5e | ||
|  | e0ca42bb88 | ||
|  | bca336bf35 | ||
|  | 6646d8acd2 | ||
|  | c66f0aeecc | ||
|  | ecb41cb150 | ||
|  | ed8db8b5f2 | ||
|  | 4ba37fce95 | ||
|  | 5b57eff9b8 | ||
|  | f980da560a | ||
|  | ffba68221b | ||
|  | 4d45e5b9b5 | ||
|  | 86d3f0aba7 | ||
|  | 66a25bd4a9 | ||
|  | 745dbedbaa | ||
|  | 26f83e75ef | ||
|  | ce72827dc7 | ||
|  | 6e8f075d42 | ||
|  | ae6c180be8 | ||
|  | 54e12d03fd | ||
|  | 469578e976 | ||
|  | 97118668e2 | ||
|  | 1c3813ce52 | ||
|  | b440e85452 | ||
|  | 0609322489 | ||
|  | b215e34650 | ||
|  | 6284a1abef | ||
|  | 41d4167533 | ||
|  | 75bc821afd | ||
|  | 39551bdc1a | ||
|  | 6412de1dd5 | ||
|  | 8d2f7fc5ef | ||
|  | ffd73c39b3 | ||
|  | 4fcee64483 | ||
|  | 203764eb51 | ||
|  | 747c9a1d3e | ||
|  | e38d0daaab | 
							
								
								
									
										421
									
								
								.drone.jsonnet
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										421
									
								
								.drone.jsonnet
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,421 @@ | ||||
| # Copyright 2022 Peter Dimov | ||||
| # Distributed under the Boost Software License, Version 1.0. | ||||
| # https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| local library = "smart_ptr"; | ||||
|  | ||||
| local triggers = | ||||
| { | ||||
|     branch: [ "master", "develop", "feature/*" ] | ||||
| }; | ||||
|  | ||||
| local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' }; | ||||
| local asan = { ASAN: '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', | ||||
|                 'echo $DRONE_STAGE_MACHINE', | ||||
|             ] + | ||||
|             (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: | ||||
|             [ | ||||
|                 '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: | ||||
|             [ | ||||
|                 'cmd /C .drone\\\\drone.bat ' + library, | ||||
|             ] | ||||
|         } | ||||
|     ] | ||||
| }; | ||||
|  | ||||
| [ | ||||
|     linux_pipeline( | ||||
|         "Linux 14.04 GCC 4.8*", | ||||
|         "cppalliance/droneubuntu1404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11' }, | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 14.04 GCC 4.9", | ||||
|         "cppalliance/droneubuntu1404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11' }, | ||||
|         "g++-4.9", | ||||
|         [ "ppa:ubuntu-toolchain-r/test" ], | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 16.04 GCC 5*", | ||||
|         "cppalliance/droneubuntu1604:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14' }, | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 18.04 GCC 6", | ||||
|         "cppalliance/droneubuntu1804:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14' }, | ||||
|         "g++-6", | ||||
|     ), | ||||
|  | ||||
|     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", | ||||
|         "cppalliance/droneubuntu1804:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11,14,17', ADDRMD: '32,64' }, | ||||
|         "g++-8-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 20.04 GCC 9* 32/64", | ||||
|         "cppalliance/droneubuntu2004:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,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", | ||||
|         "cppalliance/droneubuntu2004:multiarch", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' }, | ||||
|         arch="s390x", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 20.04 GCC 10 32/64", | ||||
|         "cppalliance/droneubuntu2004:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14,17,20', ADDRMD: '32,64' }, | ||||
|         "g++-10-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 22.04 GCC 11* 32/64", | ||||
|         "cppalliance/droneubuntu2204:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' }, | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 22.04 GCC 12 32/64", | ||||
|         "cppalliance/droneubuntu2204:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' }, | ||||
|         "g++-12-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 GCC 13 32 ASAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + asan, | ||||
|         "g++-13-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 GCC 13 32 UBSAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + ubsan, | ||||
|         "g++-13-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 GCC 13 64 UBSAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + ubsan, | ||||
|         "g++-13-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 GCC 14 UBSAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b' } + ubsan, | ||||
|         "g++-14-multilib", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 GCC 14 ASAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b' } + asan, | ||||
|         "g++-14-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' }, | ||||
|         "clang-5.0", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 20.04 Clang 6.0", | ||||
|         "cppalliance/droneubuntu2004: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,20' }, | ||||
|         "clang-12", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 22.04 Clang 13", | ||||
|         "cppalliance/droneubuntu2204:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-13", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 22.04 Clang 14", | ||||
|         "cppalliance/droneubuntu2204:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-14", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 22.04 Clang 15", | ||||
|         "cppalliance/droneubuntu2204:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-15", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 16", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-16", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 17", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-17", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 18", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-18", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 19", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-19", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 20 UBSAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '11,14,17,20,23,2c' } + ubsan, | ||||
|         "clang-20", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 20 ASAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '11,14,17,20,23,2c' } + asan, | ||||
|         "clang-20", | ||||
|     ), | ||||
|  | ||||
|     macos_pipeline( | ||||
|         "MacOS 10.15 Xcode 12.2 UBSAN", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + ubsan, | ||||
|     ), | ||||
|  | ||||
|     macos_pipeline( | ||||
|         "MacOS 10.15 Xcode 12.2 ASAN", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + asan, | ||||
|     ), | ||||
|  | ||||
|     macos_pipeline( | ||||
|         "MacOS 12.4 Xcode 13.4.1 UBSAN", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + ubsan, | ||||
|         xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64", | ||||
|     ), | ||||
|  | ||||
|     macos_pipeline( | ||||
|         "MacOS 12.4 Xcode 13.4.1 ASAN", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + asan, | ||||
|         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', B2_DONT_EMBED_MANIFEST: '1' }, | ||||
|     ), | ||||
|  | ||||
|     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' }, | ||||
|     ), | ||||
| ] | ||||
							
								
								
									
										23
									
								
								.drone/drone.bat
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.drone/drone.bat
									
									
									
									
									
										Normal file
									
								
							| @@ -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 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker | ||||
							
								
								
									
										25
									
								
								.drone/drone.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										25
									
								
								.drone/drone.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| #!/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 | ||||
|  | ||||
| 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 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} | ||||
							
								
								
									
										662
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										662
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,662 @@ | ||||
| name: CI | ||||
|  | ||||
| on: | ||||
|   pull_request: | ||||
|   push: | ||||
|     branches: | ||||
|       - master | ||||
|       - develop | ||||
|       - feature/** | ||||
|  | ||||
| env: | ||||
|   UBSAN_OPTIONS: print_stacktrace=1 | ||||
|  | ||||
| jobs: | ||||
|   posix: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - toolset: gcc-4.8 | ||||
|             cxxstd: "11" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-4.8-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-5 | ||||
|             cxxstd: "11,14,1z" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-5-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-6 | ||||
|             cxxstd: "11,14,1z" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-6-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-7 | ||||
|             cxxstd: "11,14,17" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-7-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-8 | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-8-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-9 | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-9-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-10 | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: g++-10-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-11 | ||||
|             cxxstd: "11,14,17,20" | ||||
|             os: ubuntu-22.04 | ||||
|             install: g++-11-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-12 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             os: ubuntu-22.04 | ||||
|             install: g++-12-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-13 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             os: ubuntu-latest | ||||
|             container: ubuntu:24.04 | ||||
|             install: g++-13-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-14 | ||||
|             cxxstd: "11,14,17,20,23,2c" | ||||
|             os: ubuntu-latest | ||||
|             container: ubuntu:24.04 | ||||
|             install: g++-14-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: gcc-15 | ||||
|             cxxstd: "11,14,17,20,23,2c" | ||||
|             os: ubuntu-latest | ||||
|             container: ubuntu:25.04 | ||||
|             install: g++-15-multilib | ||||
|             address-model: 32,64 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-3.9 | ||||
|             cxxstd: "11,14" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-3.9 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-4.0 | ||||
|             cxxstd: "11,14" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-4.0 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-5.0 | ||||
|             cxxstd: "11,14,1z" | ||||
|             container: ubuntu:18.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-5.0 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-6.0 | ||||
|             cxxstd: "11,14,17" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-6.0 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-7 | ||||
|             cxxstd: "11,14,17" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-7 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-8 | ||||
|             cxxstd: "11,14,17" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-8 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-9 | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-9 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-10 | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-10 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-11 | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-11 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-12 | ||||
|             cxxstd: "11,14,17,20" | ||||
|             container: ubuntu:20.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-12 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-13 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             container: ubuntu:22.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-13 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-14 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             container: ubuntu:22.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-14 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-15 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             container: ubuntu:22.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-15 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-16 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             container: ubuntu:24.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-16 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-17 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             container: ubuntu:24.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-17 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-18 | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             container: ubuntu:24.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-18 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-19 | ||||
|             cxxstd: "11,14,17,20,23,2c" | ||||
|             container: ubuntu:24.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-19 | ||||
|           - toolset: clang | ||||
|             compiler: clang++-20 | ||||
|             cxxstd: "11,14,17,20,23,2c" | ||||
|             container: ubuntu:25.04 | ||||
|             os: ubuntu-latest | ||||
|             install: clang-20 | ||||
|           - toolset: clang | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             os: macos-13 | ||||
|           - toolset: clang | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             os: macos-14 | ||||
|           - toolset: clang | ||||
|             cxxstd: "11,14,17,20,2b" | ||||
|             os: macos-15 | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     container: | ||||
|       image: ${{matrix.container}} | ||||
|       volumes: | ||||
|         - /node20217:/node20217:rw,rshared | ||||
|         - ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }} | ||||
|  | ||||
|     defaults: | ||||
|       run: | ||||
|         shell: bash | ||||
|  | ||||
|     steps: | ||||
|       - name: Setup container environment | ||||
|         if: matrix.container | ||||
|         run: | | ||||
|           apt-get update | ||||
|           apt-get -y install sudo python3 git g++ curl xz-utils | ||||
|  | ||||
|       - name: Install nodejs20glibc2.17 | ||||
|         if: ${{ startsWith( matrix.container, 'ubuntu:1' ) }} | ||||
|         run: | | ||||
|           curl -LO https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz | ||||
|           tar -xf node-v20.9.0-linux-x64-glibc-217.tar.xz --strip-components 1 -C /node20217 | ||||
|           ldd /__e/node20/bin/node | ||||
|  | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Install packages | ||||
|         if: matrix.install | ||||
|         run: | | ||||
|           sudo apt-get update | ||||
|           sudo apt-get -y install ${{matrix.install}} | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY | ||||
|           LIBRARY=${GITHUB_REPOSITORY#*/} | ||||
|           echo LIBRARY: $LIBRARY | ||||
|           echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV | ||||
|           echo GITHUB_BASE_REF: $GITHUB_BASE_REF | ||||
|           echo GITHUB_REF: $GITHUB_REF | ||||
|           REF=${GITHUB_BASE_REF:-$GITHUB_REF} | ||||
|           REF=${REF#refs/heads/} | ||||
|           echo REF: $REF | ||||
|           BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true | ||||
|           echo BOOST_BRANCH: $BOOST_BRANCH | ||||
|           cd .. | ||||
|           git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY | ||||
|           git submodule update --init tools/boostdep | ||||
|           python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY | ||||
|           ./bootstrap.sh | ||||
|           ./b2 -d0 headers | ||||
|  | ||||
|       - name: Create user-config.jam | ||||
|         if: matrix.compiler | ||||
|         run: | | ||||
|           echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam | ||||
|  | ||||
|       - name: Run tests | ||||
|         run: | | ||||
|           cd ../boost-root | ||||
|           ./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} ${ADDRMD:+address-model=$ADDRMD} variant=debug,release | ||||
|  | ||||
|   windows: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - toolset: msvc-14.3 | ||||
|             cxxstd: "14,17,20,latest" | ||||
|             addrmd: 32,64 | ||||
|             os: windows-2022 | ||||
|           - toolset: clang-win | ||||
|             cxxstd: "14,17,20,latest" | ||||
|             addrmd: 32,64 | ||||
|             os: windows-2022 | ||||
|           - toolset: gcc | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             addrmd: 64 | ||||
|             os: windows-2022 | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% | ||||
|           for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi | ||||
|           echo LIBRARY: %LIBRARY% | ||||
|           echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% | ||||
|           echo GITHUB_BASE_REF: %GITHUB_BASE_REF% | ||||
|           echo GITHUB_REF: %GITHUB_REF% | ||||
|           if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% | ||||
|           set BOOST_BRANCH=develop | ||||
|           for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master | ||||
|           echo BOOST_BRANCH: %BOOST_BRANCH% | ||||
|           cd .. | ||||
|           git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% | ||||
|           cmd /c bootstrap | ||||
|           b2 -d0 headers | ||||
|  | ||||
|       - name: Run tests | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root | ||||
|           b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker | ||||
|  | ||||
|   posix-cmake-subdir: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: ubuntu-22.04 | ||||
|           - os: ubuntu-24.04 | ||||
|           - os: macos-13 | ||||
|           - os: macos-14 | ||||
|           - os: macos-15 | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Install packages | ||||
|         if: matrix.install | ||||
|         run: sudo apt-get -y install ${{matrix.install}} | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY | ||||
|           LIBRARY=${GITHUB_REPOSITORY#*/} | ||||
|           echo LIBRARY: $LIBRARY | ||||
|           echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV | ||||
|           echo GITHUB_BASE_REF: $GITHUB_BASE_REF | ||||
|           echo GITHUB_REF: $GITHUB_REF | ||||
|           REF=${GITHUB_BASE_REF:-$GITHUB_REF} | ||||
|           REF=${REF#refs/heads/} | ||||
|           echo REF: $REF | ||||
|           BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true | ||||
|           echo BOOST_BRANCH: $BOOST_BRANCH | ||||
|           cd .. | ||||
|           git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY | ||||
|  | ||||
|       - name: Use library with add_subdirectory | ||||
|         run: | | ||||
|           cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test | ||||
|           mkdir __build__ && cd __build__ | ||||
|           cmake .. | ||||
|           cmake --build . | ||||
|           ctest --output-on-failure --no-tests=error | ||||
|  | ||||
|   posix-cmake-install: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: ubuntu-22.04 | ||||
|           - os: ubuntu-24.04 | ||||
|           - os: macos-13 | ||||
|           - os: macos-14 | ||||
|           - os: macos-15 | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Install packages | ||||
|         if: matrix.install | ||||
|         run: sudo apt-get -y install ${{matrix.install}} | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY | ||||
|           LIBRARY=${GITHUB_REPOSITORY#*/} | ||||
|           echo LIBRARY: $LIBRARY | ||||
|           echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV | ||||
|           echo GITHUB_BASE_REF: $GITHUB_BASE_REF | ||||
|           echo GITHUB_REF: $GITHUB_REF | ||||
|           REF=${GITHUB_BASE_REF:-$GITHUB_REF} | ||||
|           REF=${REF#refs/heads/} | ||||
|           echo REF: $REF | ||||
|           BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true | ||||
|           echo BOOST_BRANCH: $BOOST_BRANCH | ||||
|           cd .. | ||||
|           git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY | ||||
|  | ||||
|       - name: Configure | ||||
|         run: | | ||||
|           cd ../boost-root | ||||
|           mkdir __build__ && cd __build__ | ||||
|           cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local .. | ||||
|  | ||||
|       - name: Install | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           cmake --build . --target install | ||||
|  | ||||
|       - name: Use the installed library | ||||
|         run: | | ||||
|           cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ | ||||
|           cmake -DCMAKE_INSTALL_PREFIX=~/.local .. | ||||
|           cmake --build . | ||||
|           ctest --output-on-failure --no-tests=error | ||||
|  | ||||
|   posix-cmake-test: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: ubuntu-22.04 | ||||
|           - os: ubuntu-24.04 | ||||
|           - os: macos-13 | ||||
|           - os: macos-14 | ||||
|           - os: macos-15 | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Install packages | ||||
|         if: matrix.install | ||||
|         run: sudo apt-get -y install ${{matrix.install}} | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY | ||||
|           LIBRARY=${GITHUB_REPOSITORY#*/} | ||||
|           echo LIBRARY: $LIBRARY | ||||
|           echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV | ||||
|           echo GITHUB_BASE_REF: $GITHUB_BASE_REF | ||||
|           echo GITHUB_REF: $GITHUB_REF | ||||
|           REF=${GITHUB_BASE_REF:-$GITHUB_REF} | ||||
|           REF=${REF#refs/heads/} | ||||
|           echo REF: $REF | ||||
|           BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true | ||||
|           echo BOOST_BRANCH: $BOOST_BRANCH | ||||
|           cd .. | ||||
|           git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY | ||||
|  | ||||
|       - name: Configure | ||||
|         run: | | ||||
|           cd ../boost-root | ||||
|           mkdir __build__ && cd __build__ | ||||
|           cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON .. | ||||
|  | ||||
|       - name: Build tests | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           cmake --build . --target tests | ||||
|  | ||||
|       - name: Run tests | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           ctest --output-on-failure --no-tests=error | ||||
|  | ||||
|   windows-cmake-subdir: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: windows-latest | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% | ||||
|           for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi | ||||
|           echo LIBRARY: %LIBRARY% | ||||
|           echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% | ||||
|           echo GITHUB_BASE_REF: %GITHUB_BASE_REF% | ||||
|           echo GITHUB_REF: %GITHUB_REF% | ||||
|           if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% | ||||
|           set BOOST_BRANCH=develop | ||||
|           for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master | ||||
|           echo BOOST_BRANCH: %BOOST_BRANCH% | ||||
|           cd .. | ||||
|           git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% | ||||
|  | ||||
|       - name: Use library with add_subdirectory (Debug) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test | ||||
|           mkdir __build__ && cd __build__ | ||||
|           cmake .. | ||||
|           cmake --build . --config Debug | ||||
|           ctest --output-on-failure --no-tests=error -C Debug | ||||
|  | ||||
|       - name: Use library with add_subdirectory (Release) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__ | ||||
|           cmake --build . --config Release | ||||
|           ctest --output-on-failure --no-tests=error -C Release | ||||
|  | ||||
|   windows-cmake-install: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: windows-latest | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% | ||||
|           for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi | ||||
|           echo LIBRARY: %LIBRARY% | ||||
|           echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% | ||||
|           echo GITHUB_BASE_REF: %GITHUB_BASE_REF% | ||||
|           echo GITHUB_REF: %GITHUB_REF% | ||||
|           if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% | ||||
|           set BOOST_BRANCH=develop | ||||
|           for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master | ||||
|           echo BOOST_BRANCH: %BOOST_BRANCH% | ||||
|           cd .. | ||||
|           git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% | ||||
|  | ||||
|       - name: Configure | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root | ||||
|           mkdir __build__ && cd __build__ | ||||
|           cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. | ||||
|  | ||||
|       - name: Install (Debug) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           cmake --build . --target install --config Debug | ||||
|  | ||||
|       - name: Install (Release) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           cmake --build . --target install --config Release | ||||
|  | ||||
|       - name: Use the installed library (Debug) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__ | ||||
|           cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. | ||||
|           cmake --build . --config Debug | ||||
|           ctest --output-on-failure --no-tests=error -C Debug | ||||
|  | ||||
|       - name: Use the installed library (Release) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__ | ||||
|           cmake --build . --config Release | ||||
|           ctest --output-on-failure --no-tests=error -C Release | ||||
|  | ||||
|   windows-cmake-test: | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: windows-latest | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|  | ||||
|       - name: Setup Boost | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% | ||||
|           for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi | ||||
|           echo LIBRARY: %LIBRARY% | ||||
|           echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% | ||||
|           echo GITHUB_BASE_REF: %GITHUB_BASE_REF% | ||||
|           echo GITHUB_REF: %GITHUB_REF% | ||||
|           if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% | ||||
|           set BOOST_BRANCH=develop | ||||
|           for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master | ||||
|           echo BOOST_BRANCH: %BOOST_BRANCH% | ||||
|           cd .. | ||||
|           git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root | ||||
|           cd boost-root | ||||
|           xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ | ||||
|           git submodule update --init tools/boostdep | ||||
|           python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% | ||||
|  | ||||
|       - name: Configure | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root | ||||
|           mkdir __build__ && cd __build__ | ||||
|           cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON .. | ||||
|  | ||||
|       - name: Build tests (Debug) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           cmake --build . --target tests --config Debug | ||||
|  | ||||
|       - name: Run tests (Debug) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           ctest --output-on-failure --no-tests=error -C Debug | ||||
|  | ||||
|       - name: Build tests (Release) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           cmake --build . --target tests --config Release | ||||
|  | ||||
|       - name: Run tests (Release) | ||||
|         shell: cmd | ||||
|         run: | | ||||
|           cd ../boost-root/__build__ | ||||
|           ctest --output-on-failure --no-tests=error -C Release | ||||
							
								
								
									
										223
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,223 @@ | ||||
| # Copyright 2016-2020 Peter Dimov | ||||
| # 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) | ||||
|  | ||||
| language: cpp | ||||
|  | ||||
| dist: xenial | ||||
|  | ||||
| branches: | ||||
|   only: | ||||
|     - master | ||||
|     - develop | ||||
|     - /feature\/.*/ | ||||
|  | ||||
| env: | ||||
|   matrix: | ||||
|     - BOGUS_JOB=true | ||||
|  | ||||
| matrix: | ||||
|  | ||||
|   exclude: | ||||
|     - env: BOGUS_JOB=true | ||||
|  | ||||
|   include: | ||||
|     - os: linux | ||||
|       dist: trusty | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11 | ||||
|  | ||||
|     - os: linux | ||||
|       dist: xenial | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11,14 | ||||
|  | ||||
|     - os: linux | ||||
|       dist: bionic | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11,14,17 | ||||
|  | ||||
|     - os: linux | ||||
|       dist: focal | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11,14,17 | ||||
|  | ||||
|     - os: linux | ||||
|       arch: arm64 | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11,14 | ||||
|  | ||||
|     - os: linux | ||||
|       arch: ppc64le | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11,14 | ||||
|  | ||||
|     - os: linux | ||||
|       arch: s390x | ||||
|       compiler: g++ | ||||
|       env: TOOLSET=gcc CXXSTD=03,11,14 | ||||
|  | ||||
|     - os: freebsd | ||||
|       compiler: clang++ | ||||
|       env: TOOLSET=clang CXXSTD=03,11,14,17,2a | ||||
|  | ||||
|     - os: linux | ||||
|       compiler: g++-4.4 | ||||
|       env: TOOLSET=gcc CXXSTD=98,0x | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - g++-4.4 | ||||
|           sources: | ||||
|             - ubuntu-toolchain-r-test | ||||
|  | ||||
|     - os: linux | ||||
|       compiler: g++-4.6 | ||||
|       env: TOOLSET=gcc CXXSTD=03,0x | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - g++-4.6 | ||||
|           sources: | ||||
|             - ubuntu-toolchain-r-test | ||||
|  | ||||
|     - os: linux | ||||
|       dist: bionic | ||||
|       compiler: g++-10 | ||||
|       env: UBSAN=1 TOOLSET=gcc CXXSTD=03,11,14 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - g++-10 | ||||
|           sources: | ||||
|             - ubuntu-toolchain-r-test | ||||
|  | ||||
|     - os: linux | ||||
|       dist: bionic | ||||
|       compiler: g++-10 | ||||
|       env: UBSAN=1 TOOLSET=gcc CXXSTD=17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - g++-10 | ||||
|           sources: | ||||
|             - ubuntu-toolchain-r-test | ||||
|  | ||||
|     - os: linux | ||||
|       dist: trusty | ||||
|       compiler: /usr/bin/clang++ | ||||
|       env: TOOLSET=clang COMMENT=clang-3.3 CXXSTD=03,11 | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - clang-3.3 | ||||
|  | ||||
|     - os: linux | ||||
|       dist: trusty | ||||
|       compiler: /usr/bin/clang++ | ||||
|       env: TOOLSET=clang COMMENT=clang-3.4 CXXSTD=03,11 | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - clang-3.4 | ||||
|  | ||||
|     - os: linux | ||||
|       compiler: clang++-11 | ||||
|       env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - clang-11 | ||||
|           sources: | ||||
|             - ubuntu-toolchain-r-test | ||||
|             - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-11 main' | ||||
|               key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key' | ||||
|  | ||||
|     - os: linux | ||||
|       dist: trusty | ||||
|       compiler: clang++-libc++ | ||||
|       env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - libc++-dev | ||||
|  | ||||
|     - os: linux | ||||
|       dist: bionic | ||||
|       compiler: clang++-libc++ | ||||
|       env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 | ||||
|       addons: | ||||
|         apt: | ||||
|           packages: | ||||
|             - libc++-dev | ||||
|  | ||||
|     - os: osx | ||||
|       compiler: clang++ | ||||
|       env: UBSAN=1 TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 | ||||
|  | ||||
|     - os: linux | ||||
|       env: CMAKE_TEST=1 | ||||
|       script: | ||||
|         - mkdir __build__ && cd __build__ | ||||
|         - cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=smart_ptr -DBUILD_TESTING=ON .. | ||||
|         - cmake --build . --target tests -- -k | ||||
|         - ctest --output-on-failure -R boost_smart_ptr | ||||
|  | ||||
|     - os: linux | ||||
|       compiler: g++ | ||||
|       env: CMAKE_SUBDIR_TEST=1 | ||||
|       script: | ||||
|       - cd libs/smart_ptr/test/cmake_subdir_test && mkdir __build__ && cd __build__ | ||||
|       - cmake .. | ||||
|       - cmake --build . | ||||
|       - cmake --build . --target check | ||||
|  | ||||
|     - os: linux | ||||
|       env: CMAKE_INSTALL_TEST=1 | ||||
|       script: | ||||
|         - pip install --user cmake | ||||
|         - mkdir __build__ && cd __build__ | ||||
|         - cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=smart_ptr -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=~/.local .. | ||||
|         - cmake --build . --target install | ||||
|         - cd ../libs/smart_ptr/test/cmake_install_test && mkdir __build__ && cd __build__ | ||||
|         - cmake -DCMAKE_INSTALL_PREFIX=~/.local .. | ||||
|         - cmake --build . | ||||
|         - cmake --build . --target check | ||||
|  | ||||
| install: | ||||
|   - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true | ||||
|   - cd .. | ||||
|   - git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root | ||||
|   - cd boost-root | ||||
|   - git submodule init libs/align | ||||
|   - git submodule init libs/assert | ||||
|   - git submodule init libs/atomic | ||||
|   - git submodule init libs/config | ||||
|   - git submodule init libs/container_hash | ||||
|   - git submodule init libs/core | ||||
|   - git submodule init libs/move | ||||
|   - git submodule init libs/predef | ||||
|   - git submodule init libs/static_assert | ||||
|   - git submodule init libs/throw_exception | ||||
|   - git submodule init libs/type_traits | ||||
|   - git submodule init libs/detail | ||||
|   - git submodule init libs/integer | ||||
|   - git submodule init tools/build | ||||
|   - git submodule init libs/headers | ||||
|   - git submodule init tools/boost_install | ||||
|   - git submodule init tools/cmake | ||||
|   - git submodule init libs/preprocessor | ||||
|   - git submodule init libs/bind | ||||
|   - git submodule update # no --jobs 3 on non-amd64 | ||||
|   - cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr | ||||
|   - ./bootstrap.sh | ||||
|   - ./b2 headers | ||||
|  | ||||
| script: | ||||
|   - |- | ||||
|     echo "using $TOOLSET : : $TRAVIS_COMPILER ;" > ~/user-config.jam | ||||
|   - ./b2 -j3 libs/smart_ptr/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS} | ||||
|  | ||||
| notifications: | ||||
|   email: | ||||
|     on_success: always | ||||
							
								
								
									
										29
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| # Generated by `boostdep --cmake smart_ptr` | ||||
| # 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.8...3.20) | ||||
|  | ||||
| project(boost_smart_ptr VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) | ||||
|  | ||||
| add_library(boost_smart_ptr INTERFACE) | ||||
| add_library(Boost::smart_ptr ALIAS boost_smart_ptr) | ||||
|  | ||||
| target_include_directories(boost_smart_ptr INTERFACE include) | ||||
|  | ||||
| target_link_libraries(boost_smart_ptr | ||||
|   INTERFACE | ||||
|     Boost::assert | ||||
|     Boost::config | ||||
|     Boost::core | ||||
|     Boost::throw_exception | ||||
| ) | ||||
|  | ||||
| target_compile_features(boost_smart_ptr INTERFACE cxx_std_11) | ||||
|  | ||||
| if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") | ||||
|  | ||||
|   add_subdirectory(test) | ||||
|  | ||||
| endif() | ||||
							
								
								
									
										6
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| # Boost.SmartPtr | ||||
|  | ||||
| Branch   | Travis | Appveyor | ||||
| ---------|--------|--------- | ||||
| Develop  | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr) | ||||
| Master   | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr) | ||||
							
								
								
									
										79
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								appveyor.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| # Copyright 2016-2019 Peter Dimov | ||||
| # 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 | ||||
|     - /feature\/.*/ | ||||
|  | ||||
| environment: | ||||
|   matrix: | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 | ||||
|       TOOLSET: msvc-14.0 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 | ||||
|       TOOLSET: msvc-14.1 | ||||
|       CXXSTD: 14,17 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: 14 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: 17 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: 20 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: latest | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: clang-win | ||||
|       CXXSTD: 14,17,latest | ||||
|       ADDRMD: 64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 | ||||
|       ADDPATH: C:\cygwin\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,1z | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 | ||||
|       ADDPATH: C:\cygwin64\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,1z | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 | ||||
|       ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,17 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 | ||||
|       ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,17 | ||||
|  | ||||
| install: | ||||
|   - set BOOST_BRANCH=develop | ||||
|   - if "%APPVEYOR_REPO_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 | ||||
|   - xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\smart_ptr\ | ||||
|   - git submodule update --init tools/boostdep | ||||
|   - python tools/boostdep/depinst/depinst.py smart_ptr | ||||
|   - cmd /c bootstrap | ||||
|   - b2 -d0 headers | ||||
|  | ||||
| build: off | ||||
|  | ||||
| test_script: | ||||
|   - PATH=%ADDPATH%%PATH% | ||||
|   - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% | ||||
|   - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% | ||||
|   - b2 -j3 libs/smart_ptr/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker | ||||
							
								
								
									
										23
									
								
								build.jam
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								build.jam
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # Copyright 2023-2024 René Ferdinand Rivera Morell | ||||
| # Copyright 2024 Peter Dimov | ||||
| # Distributed under the Boost Software License, Version 1.0. | ||||
| # https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| require-b2 5.2 ; | ||||
|  | ||||
| constant boost_dependencies : | ||||
|     /boost/assert//boost_assert | ||||
|     /boost/config//boost_config | ||||
|     /boost/core//boost_core | ||||
|     /boost/throw_exception//boost_throw_exception | ||||
|     ; | ||||
|  | ||||
| project /boost/smart_ptr ; | ||||
|  | ||||
| explicit | ||||
|     [ alias boost_smart_ptr : : : : <include>include <library>$(boost_dependencies) ] | ||||
|     [ alias all : boost_smart_ptr test ] | ||||
|     ; | ||||
|  | ||||
| call-if : boost-library smart_ptr | ||||
|     ; | ||||
| @@ -1,89 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Smart Pointer Changes</title> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| 	</head> | ||||
| 	<body bgcolor="#ffffff" text="#000000"> | ||||
| 		<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86" | ||||
| 					border="0"></A>Smart Pointer Changes</h1> | ||||
| 		<p>The February 2002 change to the Boost smart pointers introduced a number of  | ||||
| 			changes. Since the previous version of the smart pointers was in use for a long  | ||||
| 			time, it's useful to have a detailed list of what changed from a library user's  | ||||
| 			point of view.</p> | ||||
| 		<p>Note that for compilers that don't support member templates well enough, a  | ||||
| 			separate implementation is used that lacks many of the new features and is more  | ||||
| 			like the old version.</p> | ||||
| 		<h2>Features Requiring Code Changes to Take Advantage</h2> | ||||
| 		<ul> | ||||
| 			<li> | ||||
| 				The smart pointer class templates now each have their own header file. For  | ||||
| 				compatibility, the <a href="../../boost/smart_ptr.hpp"><boost/smart_ptr.hpp></a> | ||||
| 			header now includes the headers for the four classic smart pointer class  | ||||
| 			templates. | ||||
| 			<li> | ||||
| 				The <b>weak_ptr</b> | ||||
| 			template was added. | ||||
| 			<li> | ||||
| 				The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that  | ||||
| 				the pointed-to object's destructor must be visible when instantiating the <b>shared_ptr</b> | ||||
| 			destructor. This makes it easier to have shared_ptr members in classes without  | ||||
| 			explicit destructors. | ||||
| 			<li> | ||||
| 				A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>. | ||||
| 			<li> | ||||
| 				<b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are  | ||||
| 				provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b> | ||||
| 				and <b>dynamic_cast</b> | ||||
| 			do for pointers. | ||||
| 			<li> | ||||
| 				The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,  | ||||
| 				although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.  | ||||
| 				Calling <b>reset</b> with a pointer to the object that's already owned by the <b>shared_ptr</b> | ||||
| 			results in undefined behavior (an assertion, or eventually a double-delete if  | ||||
| 			assertions are off). | ||||
| 			<li> | ||||
| 				The <b>BOOST_SMART_PTR_CONVERSION</b> | ||||
| 			feature has been removed. | ||||
| 			<li> | ||||
| 				<b>shared_ptr<void></b> is now allowed.</li> | ||||
| 		</ul> | ||||
| 		<h2>Features That Improve Robustness</h2> | ||||
| 		<ul> | ||||
| 			<li> | ||||
| 				The manipulation of use counts is now <a name="threadsafe">thread safe</a> on  | ||||
| 				Windows, Linux, and platforms that support pthreads. See the <a href="../../boost/detail/atomic_count.hpp"> | ||||
| 					<boost/detail/atomic_count.hpp></a> | ||||
| 			file for details | ||||
| 			<li> | ||||
| 				The new shared_ptr will always delete the object using the pointer it was  | ||||
| 				originally constructed with. This prevents subtle problems that could happen if  | ||||
| 				the last <b>shared_ptr</b> was a pointer to a sub-object of a class that did  | ||||
| 				not have a virtual destructor.</li> | ||||
| 		</ul> | ||||
| 		<h2>Implementation Details</h2> | ||||
| 		<ul> | ||||
| 			<li> | ||||
| 				Some bugs in the assignment operator implementations and in <b>reset</b> | ||||
| 			have been fixed by using the "copy and swap" idiom. | ||||
| 			<li> | ||||
| 				Assertions have been added to check preconditions of various functions;  | ||||
| 				however, since these use the new <a href="../../boost/assert.hpp"><boost/assert.hpp></a> | ||||
| 			header, the assertions are disabled by default. | ||||
| 			<li> | ||||
| 				The partial specialization of <b>std::less</b> has been replaced by <b>operator<</b> | ||||
| 			overloads which accomplish the same thing without relying on undefined  | ||||
| 			behavior. | ||||
| 			<li> | ||||
| 				The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>,  | ||||
| 				which has many of the same advantages for generic programming but does not  | ||||
| 				violate the C++ standard.</li> | ||||
| 		</ul> | ||||
| 		<hr> | ||||
| 		<p>Revised 1 February 2002</p> | ||||
| 		<p>Copyright 2002 Darin Adler. Permission to copy, use, modify, sell and distribute  | ||||
| 			this document is granted provided this copyright notice appears in all copies.  | ||||
| 			This document is provided "as is" without express or implied warranty, and with  | ||||
| 			no claim as to its suitability for any purpose.</p> | ||||
| 	</body> | ||||
| </html> | ||||
							
								
								
									
										2
									
								
								doc/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								doc/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| /html/ | ||||
| /pdf/ | ||||
							
								
								
									
										24
									
								
								doc/Jamfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								doc/Jamfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| # Copyright 2017 Peter Dimov | ||||
| #  | ||||
| # 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 | ||||
|  | ||||
| import asciidoctor ; | ||||
|  | ||||
| html smart_ptr.html : smart_ptr.adoc ; | ||||
|  | ||||
| install html_ : smart_ptr.html : <location>html ; | ||||
|  | ||||
| pdf smart_ptr.pdf : smart_ptr.adoc ; | ||||
| explicit smart_ptr.pdf ; | ||||
|  | ||||
| install pdf_ : smart_ptr.pdf : <location>pdf ; | ||||
| explicit pdf_ ; | ||||
|  | ||||
| ############################################################################### | ||||
| alias boostdoc ; | ||||
| explicit boostdoc ; | ||||
| alias boostrelease : html_ ; | ||||
| explicit boostrelease ; | ||||
							
								
								
									
										7
									
								
								doc/smart_ptr-docinfo-footer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								doc/smart_ptr-docinfo-footer.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| <style> | ||||
|  | ||||
| *:not(pre)>code { background: none; color: #600000; } | ||||
| :not(pre):not([class^=L])>code { background: none; color: #600000; } | ||||
| table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; } | ||||
|  | ||||
| </style> | ||||
							
								
								
									
										70
									
								
								doc/smart_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								doc/smart_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| # Boost.SmartPtr: The Smart Pointer Library | ||||
| Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes | ||||
| :toc: left | ||||
| :toclevels: 2 | ||||
| :idprefix: | ||||
| :listing-caption: Code Example | ||||
| :docinfo: private-footer | ||||
| :source-highlighter: rouge | ||||
| :source-language: c++ | ||||
|  | ||||
| :leveloffset: +1 | ||||
|  | ||||
| include::smart_ptr/introduction.adoc[] | ||||
| include::smart_ptr/changelog.adoc[] | ||||
| include::smart_ptr/scoped_ptr.adoc[] | ||||
| include::smart_ptr/scoped_array.adoc[] | ||||
| include::smart_ptr/shared_ptr.adoc[] | ||||
| include::smart_ptr/weak_ptr.adoc[] | ||||
| include::smart_ptr/make_shared.adoc[] | ||||
| include::smart_ptr/enable_shared_from_this.adoc[] | ||||
| include::smart_ptr/enable_shared_from.adoc[] | ||||
| include::smart_ptr/make_unique.adoc[] | ||||
| include::smart_ptr/allocate_unique.adoc[] | ||||
| include::smart_ptr/intrusive_ptr.adoc[] | ||||
| include::smart_ptr/intrusive_ref_counter.adoc[] | ||||
| include::smart_ptr/local_shared_ptr.adoc[] | ||||
| include::smart_ptr/make_local_shared.adoc[] | ||||
| include::smart_ptr/pointer_cast.adoc[] | ||||
| include::smart_ptr/pointer_to_other.adoc[] | ||||
| include::smart_ptr/atomic_shared_ptr.adoc[] | ||||
| include::smart_ptr/owner_less.adoc[] | ||||
| include::smart_ptr/owner_equal_to.adoc[] | ||||
| include::smart_ptr/owner_hash.adoc[] | ||||
|  | ||||
| // appendix | ||||
| include::smart_ptr/techniques.adoc[] | ||||
|  | ||||
| // appendix | ||||
| include::smart_ptr/history.adoc[] | ||||
|  | ||||
| // appendix, deprecated | ||||
| include::smart_ptr/shared_array.adoc[] | ||||
|  | ||||
| :leveloffset: -1 | ||||
|  | ||||
| [[copyright]] | ||||
| [appendix] | ||||
| ## Copyright and License | ||||
|  | ||||
| This documentation is | ||||
|  | ||||
| * Copyright 1999 Greg Colvin | ||||
| * Copyright 1999 Beman Dawes | ||||
| * Copyright 2002 Darin Adler | ||||
| * Copyright 2003-2020 Peter Dimov | ||||
| * Copyright 2005, 2006 Ion Gaztañaga | ||||
| * Copyright 2008 Frank Mori Hess | ||||
| * Copyright 2012-2017 Glen Fernandes | ||||
| * Copyright 2013 Andrey Semashev | ||||
|  | ||||
| and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0]. | ||||
							
								
								
									
										335
									
								
								doc/smart_ptr/allocate_unique.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								doc/smart_ptr/allocate_unique.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,335 @@ | ||||
| //// | ||||
| Copyright 2019-2021 Glen Joseph Fernandes (glenjofe@gmail.com) | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#allocate_unique] | ||||
| # allocate_unique: Creating unique_ptr | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: allocate_unique_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `allocate_unique` family of function templates provide convenient and safe | ||||
| ways to obtain a `std::unique_ptr` that manages a new object created using an | ||||
| allocator. | ||||
|  | ||||
| ## Rationale | ||||
|  | ||||
| The {cpp}14 standard introduced `std::make_unique` which used operator `new` to | ||||
| create new objects. However, there is no convenient facility in the standard | ||||
| library to use an allocator for the creation of the objects managed by | ||||
| `std::unique_ptr`. Users writing allocator aware code have often requested an | ||||
| `allocate_unique` factory function. This function is to `std::unique_ptr` what | ||||
| `std::allocate_shared` is to `std::shared_ptr`. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `allocate_unique` is defined in `<boost/smart_ptr/allocate_unique.hpp>`. | ||||
|  | ||||
| [subs=+quotes] | ||||
| ``` | ||||
| namespace boost { | ||||
|   template<class T, class A> | ||||
|   class alloc_deleter; | ||||
|  | ||||
|   template<class T, class A> | ||||
|   using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>; | ||||
|  | ||||
|   `// T is not an array` | ||||
|   template<class T, class A, class... Args> | ||||
|     std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|       allocate_unique(const A& a, Args&&... args); | ||||
|  | ||||
|   `// T is not an array` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|       allocate_unique(const A& a, type_identity_t<T>&& v); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|       allocate_unique(const A& a, std::size_t n); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>> | ||||
|       allocate_unique(const A& a); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|       allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>> | ||||
|       allocate_unique(const A& a, const remove_extent_t<T>& v); | ||||
|  | ||||
|   `// T is not an array` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<T, alloc_noinit_deleter<T, A>> | ||||
|       allocate_unique_noinit(const A& a); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<T, alloc_noinit_deleter<T, A>> | ||||
|       allocate_unique_noinit(const A& a, std::size_t n); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T, class A> | ||||
|     std::unique_ptr<remove_extent_t<T>[], alloc_noinit_deleter<T, A>> | ||||
|       allocate_unique_noinit(const A& a); | ||||
|  | ||||
|   template<class T, class U, class A> | ||||
|     allocator_pointer_t<allocator_rebind_t<A, remove_cv_t<remove_extent_t<T>>>> | ||||
|       get_allocator_pointer(const std::unique_ptr<T, | ||||
|         alloc_deleter<U, A>>& p) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Common Requirements | ||||
|  | ||||
| The common requirements that apply to all `allocate_unique` and | ||||
| `allocate_unique_noinit` overloads, unless specified otherwise, are described | ||||
| below. | ||||
|  | ||||
| Requires:: `A` shall be an _allocator_. The copy constructor and destructor | ||||
| of `A` shall not throw exceptions. | ||||
|  | ||||
| Effects:: Allocates memory for an object of type `T` or `n` objects of `U` | ||||
| (if `T` is an array type of the form `U[]` and  `n` is determined by | ||||
| arguments, as specified by the concrete overload). The object is initialized | ||||
| from arguments as specified by the concrete overload. Uses a rebound copy of | ||||
| `a` (for an unspecified `value_type`) to allocate memory. If an exception is | ||||
| thrown, the functions have no effect. | ||||
|  | ||||
| Returns:: A `std::unique_ptr` instance that stores and owns the address of the | ||||
| newly constructed object. | ||||
|  | ||||
| Postconditions:: `r.get() != 0`, where `r` is the return value. | ||||
|  | ||||
| Throws:: An exception thrown from `A::allocate`, or from the initialization of | ||||
| the object. | ||||
|  | ||||
| Remarks:: | ||||
| * When an object of an array type is specified to be initialized to a value of | ||||
| the same type `v`, this shall be interpreted to mean that each array element | ||||
| of the object is initialized to the corresponding element from `v`. | ||||
| * When an object of an array type is specified to be value-initialized, this | ||||
| shall be interpreted to mean that each array element of the object is | ||||
| value-initialized. | ||||
| * When a (sub)object of non-array type `U` is specified to be initialized to a | ||||
| value `v`, or constructed from `args\...`, `allocate_unique` shall perform this | ||||
| initialization via the expression | ||||
| `std::allocator_traits<A2>::construct(a2, p, expr)` (where `_expr_` is `v` or | ||||
| `std::forward<Args>(args)\...)` respectively), `p` points to storage suitable | ||||
| to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound | ||||
| copy of `a`. | ||||
| * When a (sub)object of non-array type `U` is specified to be | ||||
| default-initialized, `allocate_unique_noinit` shall perform this initialization | ||||
| via the expression `::new(p) U`, where `p` has type `void*` and points to | ||||
| storage suitable to hold an object of type `U`. | ||||
| * When a (sub)object of non-array type `U` is specified to be | ||||
| value-initialized, `allocate_unique` shall perform this initialization via the | ||||
| expression `std::allocator_traits<A2>::construct(a2, p)`, where `p` points to | ||||
| storage suitable to hold an object of type `U` and `a2` of type `A2` is a | ||||
| potentially rebound copy of `a`. | ||||
| * Array elements are initialized in ascending order of their addresses. | ||||
| * When the lifetime of the object managed by the return value ends, or when the | ||||
| initialization of an array element throws an exception, the initialized | ||||
| elements should be destroyed in the reverse order of their construction. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ``` | ||||
| template<class T, class A, class... Args> | ||||
|   std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|     allocate_unique(const A& a, Args&&... args); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: A `std::unique_ptr` to an object of type `T`, constructed from | ||||
| `args\...`. | ||||
| Examples:: | ||||
| * `auto p = allocate_unique<int>(a);` | ||||
| * `auto p = allocate_unique<std::vector<int>>(a, 16, 1);` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|     allocate_unique(const A& a, type_identity_t<T>&& v); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `v`. | ||||
| Example:: `auto p = allocate_unique<std::vector<int>>(a, {1, 2});` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|     allocate_unique(const A& a, std::size_t n); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: A `std::unique_ptr` to a sequence of `n` value-initialized objects of | ||||
| type `remove_extent_t<T>`. | ||||
| Examples:: | ||||
| * `auto p = allocate_unique<double[]>(a, 1024);` | ||||
| * `auto p = allocate_unique<double[][2][2]>(a, 6);` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>> | ||||
|     allocate_unique(const A& a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of known bounds. | ||||
| Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` value-initialized | ||||
| objects of type `remove_extent_t<T>`. | ||||
| Examples:: | ||||
| * `auto p = allocate_unique<double[1024]>(a);` | ||||
| * `auto p = allocate_unique<double[6][2][2]>(a);` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<T, alloc_deleter<T, A>> | ||||
|     allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: A `std::unique_ptr` to a sequence of `n` objects of type | ||||
| `remove_extent_t<T>`, each initialized to `v`. | ||||
| Examples:: | ||||
| * `auto p = allocate_unique<double[]>(a, 1024, 1.0);` | ||||
| * `auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});` | ||||
| * `auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>> | ||||
|     allocate_unique(const A& a, const remove_extent_t<T>& v); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of known bounds. | ||||
| Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` objects of type | ||||
| `remove_extent_t<T>`, each initialized to `v`. | ||||
| Examples:: | ||||
| * `auto p = allocate_unique<double[1024]>(a, 1.0);` | ||||
| * `auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});` | ||||
| * `auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<T, alloc_noinit_deleter<T, A>> | ||||
|     allocate_unique_noinit(const A& a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: A `std::unique_ptr` to a default-initialized object of type `T`. | ||||
| Example:: `auto p = allocate_unique_noinit<double>(a);` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<T, alloc_noinit_deleter<T, A>> | ||||
|     allocate_unique_noinit(const A& a, std::size_t n); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: A `std::unique_ptr` to a sequence of `n` default-initialized objects | ||||
| of type `remove_extent_t<T>`. | ||||
| Example:: `auto p = allocate_unique_noinit<double[]>(a, 1024);` | ||||
|  | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>> | ||||
|     allocate_unique_noinit(const A& a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of known bounds. | ||||
| Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` | ||||
| default-initialized objects of type `remove_extent_t<T>`. | ||||
| Example:: `auto p = allocate_unique_noinit<double[1024]>(a);` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U, class A> | ||||
|   allocator_pointer_t<allocator_rebind_t<A, remove_cv_t<remove_extent_t<T>>>> | ||||
|     get_allocator_pointer(const std::unique_ptr<T, | ||||
|       alloc_deleter<U, A>>& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: The allocator pointer to the allocation. | ||||
| Example:: `auto r = boost::get_allocator_ptr(p);` | ||||
|  | ||||
| ## Deleter | ||||
|  | ||||
| Class template `alloc_deleter` is the deleter used by the `allocate_unique` | ||||
| functions. | ||||
|  | ||||
| ### Synopsis | ||||
|  | ||||
| [subs=+quotes] | ||||
| ``` | ||||
| template<class T, class A> | ||||
| class alloc_deleter { | ||||
| public: | ||||
|   using pointer = `unspecified`; | ||||
|  | ||||
|   explicit alloc_deleter(const A& a) noexcept; | ||||
|  | ||||
|   void operator()(pointer p); | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| ### Members | ||||
|  | ||||
| [subs=+quotes] | ||||
| ``` | ||||
| using pointer = `unspecified`; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| A type that satisfies _NullablePointer_. | ||||
|  | ||||
| ``` | ||||
| explicit alloc_deleter(const A& a) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Initializes the stored allocator from `a`. | ||||
|  | ||||
| ``` | ||||
| void operator()(pointer p); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Destroys the objects and deallocates the storage referenced by `p`, | ||||
| using the stored allocator. | ||||
							
								
								
									
										170
									
								
								doc/smart_ptr/atomic_shared_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								doc/smart_ptr/atomic_shared_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#atomic_shared_ptr] | ||||
| # atomic_shared_ptr | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: atomic_shared_ptr_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The class template `atomic_shared_ptr<T>` implements the interface of `std::atomic` | ||||
| for a contained value of type `shared_ptr<T>`. Concurrent access to `atomic_shared_ptr` | ||||
| is not a data race. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `atomic_shared_ptr` is defined in `<boost/smart_ptr/atomic_shared_ptr.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class atomic_shared_ptr { | ||||
|   private: | ||||
|  | ||||
|     shared_ptr<T> p_; // exposition only | ||||
|  | ||||
|     atomic_shared_ptr(const atomic_shared_ptr&) = delete; | ||||
|     atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete; | ||||
|  | ||||
|   public: | ||||
|  | ||||
|     constexpr atomic_shared_ptr() noexcept; | ||||
|     atomic_shared_ptr( shared_ptr<T> p ) noexcept; | ||||
|  | ||||
|     atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept; | ||||
|  | ||||
|     bool is_lock_free() const noexcept; | ||||
|  | ||||
|     shared_ptr<T> load( int = 0 ) const noexcept; | ||||
|     operator shared_ptr<T>() const noexcept; | ||||
|  | ||||
|     void store( shared_ptr<T> r, int = 0 ) noexcept; | ||||
|  | ||||
|     shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept; | ||||
|  | ||||
|     bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept; | ||||
|     bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept; | ||||
|     bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept; | ||||
|     bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept; | ||||
|  | ||||
|     bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept; | ||||
|     bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept; | ||||
|     bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept; | ||||
|     bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept; | ||||
|   }; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ``` | ||||
| constexpr atomic_shared_ptr() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Default-initializes `p_`. | ||||
|  | ||||
| ``` | ||||
| atomic_shared_ptr( shared_ptr<T> p ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Initializes `p_` to `p`. | ||||
|  | ||||
| ``` | ||||
| atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `p_.swap(r)`. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ``` | ||||
| bool is_lock_free() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `false`. | ||||
|  | ||||
| NOTE: This implementation is not lock-free. | ||||
|  | ||||
| ``` | ||||
| shared_ptr<T> load( int = 0 ) const noexcept; | ||||
| ``` | ||||
| ``` | ||||
| operator shared_ptr<T>() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `p_`. | ||||
|  | ||||
| NOTE: The `int` argument is intended to be of type `memory_order`, but is ignored. | ||||
|   This implementation is lock-based and therefore always sequentially consistent. | ||||
|  | ||||
| ``` | ||||
| void store( shared_ptr<T> r, int = 0 ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `p_.swap(r)`. | ||||
|  | ||||
| ``` | ||||
| shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `p_.swap(r)`. | ||||
| Returns:: The old value of `p_`. | ||||
|  | ||||
| ``` | ||||
| bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: If `p_` is equivalent to `v`, assigns `w` to `p_`, otherwise assigns `p_` to `v`. | ||||
| Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise. | ||||
| Remarks:: Two `shared_ptr` instances are equivalent if they store the same pointer value and _share ownership_. | ||||
|  | ||||
| ``` | ||||
| bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: If `p_` is equivalent to `v`, assigns `std::move(w)` to `p_`, otherwise assigns `p_` to `v`. | ||||
| Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise. | ||||
| Remarks:: The old value of `w` is not preserved in either case. | ||||
							
								
								
									
										56
									
								
								doc/smart_ptr/changelog.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								doc/smart_ptr/changelog.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| //// | ||||
| Copyright 2019-2025 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#changelog] | ||||
| # Revision History | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: changelog_ | ||||
|  | ||||
| ## Changes in 1.88.0 | ||||
|  | ||||
| * Fix `operator<<` for wide streams (accidentally broken in 1.87.0) | ||||
|  | ||||
| ## Changes in 1.87.0 | ||||
|  | ||||
| * {cpp}03 is no longer supported, a {cpp}11 compiler is required. | ||||
|   This includes GCC 4.8 or later, and MSVC 14.0 or later. | ||||
| * The functionality enabled by the macros `BOOST_SP_ENABLE_DEBUG_HOOKS`, | ||||
|   `BOOST_SP_USE_STD_ALLOCATOR`, `BOOST_SP_USE_QUICK_ALLOCATOR`, | ||||
|   `BOOST_AC_USE_SPINLOCK`, `BOOST_AC_USE_PTHREADS`, `BOOST_SP_USE_SPINLOCK`, | ||||
|   and `BOOST_SP_USE_PTHREADS` has been deprecated and support for it | ||||
|   will be removed in a future release. | ||||
|  | ||||
| ## Changes in 1.79.0 | ||||
|  | ||||
| * Added `get_allocator_pointer` | ||||
|  | ||||
| ## Changes in 1.74.0 | ||||
|  | ||||
| * Added `owner_equals` to `shared_ptr`, `weak_ptr`, `local_shared_ptr` | ||||
| * Added `owner_hash_value` to `shared_ptr`, `weak_ptr` | ||||
| * Added `owner_equal_to`, `owner_hash` | ||||
| * Added `std::hash` specializations for `shared_ptr`, `local_shared_ptr` | ||||
| * Added `boost::hash` support to, and `std::hash`, `std::equal_to` | ||||
|   specializations for, `weak_ptr` | ||||
|  | ||||
| ## Changes in 1.72.0 | ||||
|  | ||||
| * Added `allocate_unique` | ||||
|  | ||||
| ## Changes in 1.71.0 | ||||
|  | ||||
| * Added aliasing constructors to `weak_ptr` | ||||
| * Added `weak_ptr<T>::empty()` | ||||
| * Added `enable_shared_from`, `shared_from`, and `weak_from` | ||||
|  | ||||
| ## Changes in 1.65.0 | ||||
|  | ||||
| * Added `atomic_shared_ptr` | ||||
| * Added `local_shared_ptr`, `make_local_shared` | ||||
							
								
								
									
										89
									
								
								doc/smart_ptr/enable_shared_from.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								doc/smart_ptr/enable_shared_from.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| //// | ||||
| Copyright 2002, 2003, 2015, 2017, 2019 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#enable_shared_from] | ||||
| # enable_shared_from | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: enable_shared_from_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| `enable_shared_from` is used as a base class that allows a `shared_ptr` or a | ||||
| `weak_ptr` to be obtained given a raw pointer to the object, by using the | ||||
| functions `shared_from` and `weak_from`. | ||||
|  | ||||
| `enable_shared_from` differs from `enable_shared_from_this<T>` by the fact | ||||
| that it's not a template, and is its recommended replacement for new code. | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| ``` | ||||
| #include <boost/smart_ptr/enable_shared_from.hpp> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <cassert> | ||||
|  | ||||
| class Y: public boost::enable_shared_from | ||||
| { | ||||
| public: | ||||
|  | ||||
|     boost::shared_ptr<Y> f() | ||||
|     { | ||||
|         return boost::shared_from( this ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     boost::shared_ptr<Y> p(new Y); | ||||
|     boost::shared_ptr<Y> q = p->f(); | ||||
|     assert(p == q); | ||||
|     assert(!(p < q || q < p)); // p and q must share ownership | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `enable_shared_from` is defined in `<boost/smart_ptr/enable_shared_from.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   class enable_shared_from: public enable_shared_from_this<enable_shared_from> | ||||
|   { | ||||
|   }; | ||||
|  | ||||
|   template<class T> shared_ptr<T> shared_from( T * p ); | ||||
|   template<class T> weak_ptr<T> weak_from( T * p ) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Functions | ||||
|  | ||||
| ``` | ||||
| template<class T> shared_ptr<T> shared_from( T * p ); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `shared_ptr<T>( p\->enable_shared_from::shared_from_this(), p )`. | ||||
|  | ||||
| NOTE: Throws `bad_weak_ptr` when `p` is not owned by a `shared_ptr`. | ||||
|  | ||||
| ``` | ||||
| template<class T> weak_ptr<T> weak_from( T * p ) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `weak_ptr<T>( p\->enable_shared_from::weak_from_this(), p )`. | ||||
|  | ||||
| NOTE: Unlike `shared_from(this)`, `weak_from(this)` is valid in a destructor | ||||
|       and returns a `weak_ptr` that is `expired()` but still shares ownership | ||||
|       with other `weak_ptr` instances (if any) that refer to the object. | ||||
							
								
								
									
										148
									
								
								doc/smart_ptr/enable_shared_from_this.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								doc/smart_ptr/enable_shared_from_this.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| //// | ||||
| Copyright 2002, 2003, 2015, 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#enable_shared_from_this] | ||||
| # enable_shared_from_this | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: enable_shared_from_this_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The class template `enable_shared_from_this` is used as a base class that allows | ||||
| a `shared_ptr` or a `weak_ptr` to the current object to be obtained from within a | ||||
| member function. | ||||
|  | ||||
| `enable_shared_from_this<T>` defines two member functions called `shared_from_this` | ||||
| that return a `shared_ptr<T>` and `shared_ptr<T const>`, depending on constness, to | ||||
| `this`. It also defines two member functions called `weak_from_this` that return a | ||||
| corresponding `weak_ptr`. | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| ``` | ||||
| #include <boost/enable_shared_from_this.hpp> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <cassert> | ||||
|  | ||||
| class Y: public boost::enable_shared_from_this<Y> | ||||
| { | ||||
| public: | ||||
|  | ||||
|     boost::shared_ptr<Y> f() | ||||
|     { | ||||
|         return shared_from_this(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     boost::shared_ptr<Y> p(new Y); | ||||
|     boost::shared_ptr<Y> q = p->f(); | ||||
|     assert(p == q); | ||||
|     assert(!(p < q || q < p)); // p and q must share ownership | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `enable_shared_from_this` is defined in `<boost/smart_ptr/enable_shared_from_this.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class enable_shared_from_this { | ||||
|   private: | ||||
|  | ||||
|     // exposition only | ||||
|     weak_ptr<T> weak_this_; | ||||
|  | ||||
|   protected: | ||||
|  | ||||
|     enable_shared_from_this() = default; | ||||
|     ~enable_shared_from_this() = default; | ||||
|  | ||||
|     enable_shared_from_this(const enable_shared_from_this&) noexcept; | ||||
|     enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; | ||||
|  | ||||
|   public: | ||||
|  | ||||
|     shared_ptr<T> shared_from_this(); | ||||
|     shared_ptr<T const> shared_from_this() const; | ||||
|  | ||||
|     weak_ptr<T> weak_from_this() noexcept; | ||||
|     weak_ptr<T const> weak_from_this() const noexcept; | ||||
|   } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ``` | ||||
| enable_shared_from_this(enable_shared_from_this const &) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Default-constructs `weak_this_`. | ||||
|  | ||||
| NOTE: `weak_this_` is _not_ copied from the argument. | ||||
|  | ||||
| ``` | ||||
| enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `*this`. | ||||
|  | ||||
| NOTE: `weak_this_` is unchanged. | ||||
|  | ||||
| ``` | ||||
| template<class T> shared_ptr<T> shared_from_this(); | ||||
| ``` | ||||
| ``` | ||||
| template<class T> shared_ptr<T const> shared_from_this() const; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `shared_ptr<T>(weak_this_)`. | ||||
|  | ||||
| NOTE: These members throw `bad_weak_ptr` when `*this` is not owned by a `shared_ptr`. | ||||
|  | ||||
| [NOTE] | ||||
| ==== | ||||
| `weak_this_` is initialized by `shared_ptr` to a copy of itself when it's constructed by a pointer to `*this`. | ||||
| For example, in the following code: | ||||
| ``` | ||||
| class Y: public boost::enable_shared_from_this<Y> {}; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     boost::shared_ptr<Y> p(new Y); | ||||
| } | ||||
| ``` | ||||
| the construction of `p` will automatically initialize `p\->weak_this_` to `p`. | ||||
| ==== | ||||
|  | ||||
| ``` | ||||
| template<class T> weak_ptr<T> weak_from_this() noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T> weak_ptr<T const> weak_from_this() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `weak_this_`. | ||||
|  | ||||
| NOTE: Unlike `shared_from_this()`, `weak_from_this()` is valid in a destructor | ||||
|       and returns a `weak_ptr` that is `expired()` but still shares ownership | ||||
|       with other `weak_ptr` instances (if any) that refer to the object. | ||||
							
								
								
									
										117
									
								
								doc/smart_ptr/history.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								doc/smart_ptr/history.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,117 @@ | ||||
| //// | ||||
| Copyright 1999 Greg Colvin and Beman Dawes | ||||
| Copyright 2002 Darin Adler | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [[history]] | ||||
| [appendix] | ||||
| # History and Acknowledgments | ||||
| :idprefix: history_ | ||||
|  | ||||
| ## Summer 1994 | ||||
|  | ||||
| Greg Colvin http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf[proposed] | ||||
| to the {cpp} Standards Committee classes named `auto_ptr` and `counted_ptr` which were very | ||||
| similar to what we now call `scoped_ptr` and `shared_ptr`. In one of the very few cases | ||||
| where the Library Working Group's recommendations were not followed by the full committee, | ||||
| `counted_ptr` was rejected and surprising transfer-of-ownership semantics were added to `auto_ptr`. | ||||
|  | ||||
| ## October 1998 | ||||
|  | ||||
| Beman Dawes proposed reviving the original semantics under the names `safe_ptr` and `counted_ptr`, | ||||
| meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, | ||||
| Dietmar Kühl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new class | ||||
| names were finalized, it was decided that there was no need to exactly follow the `std::auto_ptr` | ||||
| interface, and various function signatures and semantics were finalized. | ||||
|  | ||||
| Over the next three months, several implementations were considered for `shared_ptr`, and discussed | ||||
| on the http://www.boost.org/[boost.org] mailing list. The implementation questions revolved around | ||||
| the reference count which must be kept, either attached to the pointed to object, or detached elsewhere. | ||||
| Each of those variants have themselves two major variants: | ||||
|  | ||||
| * Direct detached: the `shared_ptr` contains a pointer to the object, and a pointer to the count.  | ||||
| * Indirect detached: the `shared_ptr` contains a pointer to a helper object, which in turn contains a pointer to the object and the count.  | ||||
| * Embedded attached: the count is a member of the object pointed to.  | ||||
| * Placement attached: the count is attached via operator new manipulations. | ||||
|  | ||||
| Each implementation technique has advantages and disadvantages. We went so far as to run various timings | ||||
| of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little | ||||
| measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar Kühl | ||||
| suggested an elegant partial template specialization technique to allow users to choose which implementation | ||||
| they preferred, and that was also experimented with. | ||||
|  | ||||
| But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose | ||||
| to supply only the direct implementation. | ||||
|  | ||||
| ## May 1999 | ||||
|  | ||||
| In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements. | ||||
|  | ||||
| ## September 1999 | ||||
|  | ||||
| Luis Coelho provided `shared_ptr::swap` and `shared_array::swap`. | ||||
|  | ||||
| ## November 1999 | ||||
|  | ||||
| Darin Adler provided `operator ==`, `operator !=`, and `std::swap` and `std::less` specializations for shared types. | ||||
|  | ||||
| ## May 2001 | ||||
|  | ||||
| Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams, | ||||
| Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others. | ||||
|  | ||||
| ## January 2002 | ||||
|  | ||||
| Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding | ||||
| `weak_ptr`. | ||||
|  | ||||
| ## March 2003 | ||||
|  | ||||
| Peter Dimov, Beman Dawes and Greg Colvin http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html[proposed] `shared_ptr` | ||||
| and `weak_ptr` for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was | ||||
| accepted and eventually went on to become a part of the {cpp} standard in its 2011 iteration. | ||||
|  | ||||
| ## July 2007 | ||||
|  | ||||
| Peter Dimov and Beman Dawes http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm[proposed] a number of enhancements | ||||
| to `shared_ptr` as it was entering the working paper that eventually became the {cpp}11 standard. | ||||
|  | ||||
| ## November 2012 | ||||
|  | ||||
| Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation | ||||
| for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization | ||||
| and no value initialization. | ||||
|  | ||||
| Peter Dimov aided this development by extending `shared_ptr` to support arrays via the syntax `shared_ptr<T[]>` and `shared_ptr<T[N]>`. | ||||
|  | ||||
| ## April 2013 | ||||
|  | ||||
| Peter Dimov http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.html[proposed] the extension of `shared_ptr` to support | ||||
| arrays for inclusion into the standard, and it was accepted. | ||||
|  | ||||
| ## February 2014 | ||||
|  | ||||
| Glen Fernandes updated `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper | ||||
| http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], and implemented `make_unique` for arrays and objects. | ||||
|  | ||||
| Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve {cpp} standard library defect 2070. | ||||
|  | ||||
| ## February 2017 | ||||
|  | ||||
| Glen Fernandes rewrote `allocate_shared` and `make_shared` for arrays for a more optimal and more maintainable implementation. | ||||
|  | ||||
| ## June 2017 | ||||
|  | ||||
| Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format. | ||||
|  | ||||
| Peter Dimov added `atomic_shared_ptr` and `local_shared_ptr`. | ||||
|  | ||||
| ## August 2019 | ||||
|  | ||||
| Glen Fernandes implemented `allocate_unique` for scalars and arrays. | ||||
							
								
								
									
										53
									
								
								doc/smart_ptr/introduction.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								doc/smart_ptr/introduction.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| //// | ||||
| Copyright 1999 Greg Colvin and Beman Dawes | ||||
| Copyright 2002 Darin Adler | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#introduction] | ||||
| # Introduction | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: intro_ | ||||
|  | ||||
| Smart pointers are objects which store pointers to dynamically allocated (heap) objects. | ||||
| They behave much like built-in {cpp} pointers except that they automatically delete the object | ||||
| pointed to at the appropriate time. Smart pointers are particularly useful in the face of | ||||
| exceptions as they ensure proper destruction of dynamically allocated objects. They can also be | ||||
| used to keep track of dynamically allocated objects shared by multiple owners. | ||||
|  | ||||
| Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for | ||||
| deletion of the object when it is no longer needed. As such, they are examples of the "resource | ||||
| acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ Programming Language", | ||||
| 3rd edition, Section 14.4, Resource Management. | ||||
|  | ||||
| This library provides six smart pointer class templates: | ||||
|  | ||||
| * `<<scoped_ptr,scoped_ptr>>`, used to contain ownership of a dynamically allocated object to the current scope; | ||||
| * `<<scoped_array,scoped_array>>`, which provides scoped ownership for a dynamically allocated array; | ||||
| * `<<shared_ptr,shared_ptr>>`, a versatile tool for managing shared ownership of an object or array; | ||||
| * `<<weak_ptr,weak_ptr>>`, a non-owning observer to a `shared_ptr`-managed object that can be promoted temporarily to `shared_ptr`; | ||||
| * `<<intrusive_ptr,intrusive_ptr>>`, a pointer to objects with an embedded reference count; | ||||
| * `<<local_shared_ptr,local_shared_ptr>>`, providing shared ownership within a single thread. | ||||
|  | ||||
| `shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration. | ||||
|  | ||||
| In addition, the library contains the following supporting utility functions and classes: | ||||
|  | ||||
| * `<<make_shared,make_shared>>` and `allocate_shared`, factory functions for creating objects that return a `shared_ptr`; | ||||
| * `<<make_unique,make_unique>>`, a factory function returning `std::unique_ptr`; | ||||
| * `<<allocate_unique,allocate_unique>>`, a factory function for creating objects using an allocator that returns a `std::unique_ptr`; | ||||
| * `<<enable_shared_from_this,enable_shared_from_this>>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; | ||||
| * `<<enable_shared_from,enable_shared_from>>`, a newer and better replacement for `enable_shared_from_this`; | ||||
| * `<<pointer_to_other,pointer_to_other>>`, a helper trait for converting one smart pointer type to another; | ||||
| * `<<pointer_cast,static_pointer_cast>>` and companions, generic smart pointer casts; | ||||
| * `<<intrusive_ref_counter,intrusive_ref_counter>>`, a helper base class containing a reference count. | ||||
| * `<<atomic_shared_ptr,atomic_shared_ptr>>`, a helper class implementing the interface of `std::atomic` for a value of type `shared_ptr`. | ||||
|  | ||||
| As a general rule, the destructor or `operator delete` for an object managed by pointers in the library | ||||
| are not allowed to throw exceptions. | ||||
							
								
								
									
										487
									
								
								doc/smart_ptr/intrusive_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										487
									
								
								doc/smart_ptr/intrusive_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,487 @@ | ||||
| //// | ||||
| Copyright 2003-2005, 2013, 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#intrusive_ptr] | ||||
| # intrusive_ptr: Managing Objects with Embedded Counts | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: intrusive_ptr_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count. | ||||
| Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the | ||||
| function `intrusive_ptr_add_ref`, passing it the pointer as an argument. Similarly, when an `intrusive_ptr` | ||||
| is destroyed, it calls `intrusive_ptr_release`; this function is responsible for destroying the object when | ||||
| its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. | ||||
| On compilers that support argument-dependent lookup, `intrusive_ptr_add_ref` and `intrusive_ptr_release` should | ||||
| be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace | ||||
| `boost`. The library provides a helper base class template `<<intrusive_ref_counter,intrusive_ref_counter>>` which | ||||
| may help adding support for `intrusive_ptr` to user types. | ||||
|  | ||||
| The class template is parameterized on `T`, the type of the object pointed to. `intrusive_ptr<T>` can be implicitly | ||||
| converted to `intrusive_ptr<U>` whenever `T*` can be implicitly converted to `U*`. | ||||
|  | ||||
| The main reasons to use `intrusive_ptr` are: | ||||
|  | ||||
| * Some existing frameworks or OSes provide objects with embedded reference counts; | ||||
| * The memory footprint of `intrusive_ptr` is the same as the corresponding raw pointer; | ||||
| * `intrusive_ptr<T>` can be constructed from an arbitrary raw pointer of type `T*`. | ||||
|  | ||||
| As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your needs than `shared_ptr`, try a `shared_ptr`-based design first. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `intrusive_ptr` is defined in `<boost/smart_ptr/intrusive_ptr.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class intrusive_ptr { | ||||
|   public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     intrusive_ptr() noexcept; | ||||
|     intrusive_ptr(T * p, bool add_ref = true); | ||||
|  | ||||
|     intrusive_ptr(intrusive_ptr const & r); | ||||
|     template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r); | ||||
|  | ||||
|     intrusive_ptr(intrusive_ptr && r); | ||||
|     template<class Y> intrusive_ptr(intrusive_ptr<Y> && r); | ||||
|  | ||||
|     ~intrusive_ptr(); | ||||
|  | ||||
|     intrusive_ptr & operator=(intrusive_ptr const & r); | ||||
|     template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); | ||||
|     intrusive_ptr & operator=(T * r); | ||||
|  | ||||
|     intrusive_ptr & operator=(intrusive_ptr && r); | ||||
|     template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r); | ||||
|  | ||||
|     void reset(); | ||||
|     void reset(T * r); | ||||
|     void reset(T * r, bool add_ref); | ||||
|  | ||||
|     T & operator*() const noexcept; | ||||
|     T * operator->() const noexcept; | ||||
|     T * get() const noexcept; | ||||
|     T * detach() noexcept; | ||||
|  | ||||
|     explicit operator bool () const noexcept; | ||||
|  | ||||
|     void swap(intrusive_ptr & b) noexcept; | ||||
|   }; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator==(intrusive_ptr<T> const & a, U * b) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator==(T * a, intrusive_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T> | ||||
|     bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept; | ||||
|  | ||||
|   template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept; | ||||
|  | ||||
|   template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   template<class E, class T, class Y> | ||||
|     std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, | ||||
|       intrusive_ptr<Y> const & p); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### element_type | ||||
|  | ||||
| ``` | ||||
| typedef T element_type; | ||||
| ``` | ||||
|  | ||||
| Provides the type of the template parameter T. | ||||
|  | ||||
| ### constructors | ||||
|  | ||||
| ``` | ||||
| intrusive_ptr() noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Postconditions:: `get() == 0`. | ||||
|  | ||||
| ``` | ||||
| intrusive_ptr(T * p, bool add_ref = true); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `if(p != 0 && add_ref) intrusive_ptr_add_ref(p);`. | ||||
| Postconditions:: `get() == p`. | ||||
|  | ||||
| ``` | ||||
| intrusive_ptr(intrusive_ptr const & r); | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`. | ||||
| Postconditions:: `get() == r.get()`. | ||||
|  | ||||
| ``` | ||||
| intrusive_ptr(intrusive_ptr && r); | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> intrusive_ptr(intrusive_ptr<Y> && r); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Postconditions:: | ||||
|   `get()` equals the old value of `r.get()`. `r.get() == 0`. | ||||
|  | ||||
| ### destructor | ||||
|  | ||||
| ``` | ||||
| ~intrusive_ptr(); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   `if(get() != 0) intrusive_ptr_release(get());`. | ||||
|  | ||||
| ### assignment | ||||
|  | ||||
| ``` | ||||
| intrusive_ptr & operator=(intrusive_ptr const & r); | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); | ||||
| ``` | ||||
| ``` | ||||
| intrusive_ptr & operator=(T * r); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ``` | ||||
| intrusive_ptr & operator=(intrusive_ptr && r); | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `intrusive_ptr(std::move(r)).swap(*this)`. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ### reset | ||||
|  | ||||
| ``` | ||||
| void reset(); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `intrusive_ptr().swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| void reset(T * r); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| void reset(T * r, bool add_ref); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Equivalent to `intrusive_ptr(r, add_ref).swap(*this)`. | ||||
|  | ||||
| ### indirection | ||||
|  | ||||
| ``` | ||||
| T & operator*() const noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requirements:: `get() != 0`. | ||||
| Returns:: `*get()`. | ||||
|  | ||||
| ``` | ||||
| T * operator->() const noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requirements:: `get() != 0`. | ||||
| Returns:: `get()`. | ||||
|  | ||||
| ### get | ||||
|  | ||||
| ``` | ||||
| T * get() const noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   the stored pointer. | ||||
|  | ||||
| ### detach | ||||
|  | ||||
| ``` | ||||
| T * detach() noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: the stored pointer. | ||||
| Postconditions:: `get() == 0`. | ||||
|  | ||||
| NOTE: The returned pointer has an elevated reference count. This allows conversion of an `intrusive_ptr` | ||||
| back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference. | ||||
| It can be viewed as the complement of the non-reference-incrementing constructor. | ||||
|  | ||||
| CAUTION: Using `detach` escapes the safety of automatic reference counting provided by `intrusive_ptr`. | ||||
| It should by used only where strictly necessary (such as when interfacing to an existing API), and when | ||||
| the implications are thoroughly understood. | ||||
|  | ||||
| ### conversions | ||||
|  | ||||
| ``` | ||||
| explicit operator bool () const noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `get() != 0`. | ||||
|  | ||||
| NOTE: This conversion operator allows `intrusive_ptr` objects to be used in boolean contexts, | ||||
| like `if (p && p\->valid()) {}`. | ||||
|  | ||||
| NOTE: On C++03 compilers, the return value is of an unspecified type. | ||||
|  | ||||
| ### swap | ||||
|  | ||||
| ``` | ||||
| void swap(intrusive_ptr & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Exchanges the contents of the two smart pointers. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### comparison | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.get() == b.get()`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.get() != b.get()`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator==(intrusive_ptr<T> const & a, U * b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.get() == b`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.get() != b`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator==(T * a, intrusive_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a == b.get()`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a != b.get()`. | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `std::less<T *>()(a.get(), b.get())`. | ||||
|  | ||||
| NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers. | ||||
|  | ||||
| ### swap | ||||
|  | ||||
| ``` | ||||
| template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Equivalent to `a.swap(b)`. | ||||
|  | ||||
| ### get_pointer | ||||
|  | ||||
| ``` | ||||
| template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `p.get()`. | ||||
|  | ||||
| NOTE: Provided as an aid to generic programming. Used by `mem_fn`. | ||||
|  | ||||
| ### static_pointer_cast | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `intrusive_ptr<T>(static_cast<T*>(r.get()))`. | ||||
|  | ||||
| ### const_pointer_cast | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `intrusive_ptr<T>(const_cast<T*>(r.get()))`. | ||||
|  | ||||
| ### dynamic_pointer_cast | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `intrusive_ptr<T>(dynamic_cast<T*>(r.get()))`. | ||||
|  | ||||
| ### operator<< | ||||
|  | ||||
| ``` | ||||
| template<class E, class T, class Y> | ||||
|   std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, | ||||
|     intrusive_ptr<Y> const & p); | ||||
| ``` | ||||
|  | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `os << p.get();`. | ||||
| Returns:: `os`. | ||||
							
								
								
									
										155
									
								
								doc/smart_ptr/intrusive_ref_counter.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								doc/smart_ptr/intrusive_ref_counter.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
| Copyright 2013 Andrey Semashev | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#intrusive_ref_counter] | ||||
| # intrusive_ref_counter | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: intrusive_ref_counter_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `intrusive_ref_counter` class template implements a reference counter for | ||||
| a derived user's class that is intended to be used with `intrusive_ptr`. The | ||||
| base class has associated `intrusive_ptr_add_ref` and `intrusive_ptr_release` | ||||
| functions which modify the reference counter as needed and destroy the user's | ||||
| object when the counter drops to zero. | ||||
|  | ||||
| The class template is parameterized on `Derived` and `CounterPolicy` | ||||
| parameters. The first parameter is the user's class that derives from | ||||
| `intrusive_ref_counter`. This type is needed in order to destroy the object | ||||
| correctly when there are no references to it left. | ||||
|  | ||||
| The second parameter is a policy that defines the nature of the reference | ||||
| counter. The library provides two such policies: `thread_unsafe_counter` and | ||||
| `thread_safe_counter`. The former instructs the `intrusive_ref_counter` base | ||||
| class to use a counter only suitable for a single-threaded use. Pointers to a | ||||
| single object that uses this kind of reference counter must not be used in | ||||
| different threads. The latter policy makes the reference counter thread-safe, | ||||
| unless the target platform doesn't support threading. Since in modern systems | ||||
| support for threading is common, the default counter policy is | ||||
| `thread_safe_counter`. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `intrusive_ref_counter` is defined in | ||||
| `<boost/smart_ptr/intrusive_ref_counter.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|   struct thread_unsafe_counter; | ||||
|   struct thread_safe_counter; | ||||
|  | ||||
|   template<class Derived, class CounterPolicy = thread_safe_counter> | ||||
|   class intrusive_ref_counter { | ||||
|   public: | ||||
|     intrusive_ref_counter() noexcept; | ||||
|     intrusive_ref_counter(const intrusive_ref_counter& v) noexcept; | ||||
|  | ||||
|     intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; | ||||
|  | ||||
|     unsigned int use_count() const noexcept; | ||||
|  | ||||
|   protected: | ||||
|     ~intrusive_ref_counter() = default; | ||||
|   }; | ||||
|  | ||||
|   template<class Derived, class CounterPolicy> | ||||
|     void intrusive_ptr_add_ref( | ||||
|       const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; | ||||
|  | ||||
|   template<class Derived, class CounterPolicy> | ||||
|     void intrusive_ptr_release( | ||||
|       const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### Constructors | ||||
|  | ||||
| ``` | ||||
| intrusive_ref_counter() noexcept; | ||||
| ``` | ||||
| ``` | ||||
| intrusive_ref_counter(const intrusive_ref_counter&) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Postconditions:: `use_count() == 0`. | ||||
|  | ||||
| NOTE: The pointer to the constructed object is expected to be passed to | ||||
| `intrusive_ptr` constructor, assignment operator or `reset` method, which | ||||
| would increment the reference counter. | ||||
|  | ||||
| ### Destructor | ||||
|  | ||||
| ``` | ||||
| ~intrusive_ref_counter(); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Destroys the counter object. | ||||
|  | ||||
| NOTE: The destructor is protected so that the object can only be destroyed | ||||
| through the `Derived` class. | ||||
|  | ||||
| ### Assignment | ||||
|  | ||||
| ``` | ||||
| intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Does nothing, reference counter is not modified. | ||||
|  | ||||
| ### use_count | ||||
|  | ||||
| ``` | ||||
| unsigned int use_count() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: The current value of the reference counter. | ||||
|  | ||||
| NOTE: The returned value may not be actual in multi-threaded applications. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### intrusive_ptr_add_ref | ||||
|  | ||||
| ``` | ||||
| template<class Derived, class CounterPolicy> | ||||
|   void intrusive_ptr_add_ref( | ||||
|     const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Increments the reference counter. | ||||
|  | ||||
| ### intrusive_ptr_release | ||||
|  | ||||
| ``` | ||||
| template<class Derived, class CounterPolicy> | ||||
|   void intrusive_ptr_release( | ||||
|     const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Decrements the reference counter. If the reference counter reaches | ||||
| 0, calls `delete static_cast<const Derived*>(p)`. | ||||
							
								
								
									
										738
									
								
								doc/smart_ptr/local_shared_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										738
									
								
								doc/smart_ptr/local_shared_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,738 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#local_shared_ptr] | ||||
| # local_shared_ptr: Shared Ownership within a Single Thread | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: local_shared_ptr_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| `local_shared_ptr` is nearly identical to `shared_ptr`, with the only difference of note being that its reference count is | ||||
| updated with non-atomic operations. As such, a `local_shared_ptr` and all its copies must reside in (be local to) a single | ||||
| thread (hence the name.) | ||||
|  | ||||
| `local_shared_ptr` can be converted to `shared_ptr` and vice versa. Creating a `local_shared_ptr` from a `shared_ptr` creates | ||||
| a new local reference count; this means that two `local_shared_ptr` instances, both created from the same `shared_ptr`, refer | ||||
| to the same object but don't share the same count, and as such, can safely be used by two different threads. | ||||
|  | ||||
| .Two local_shared_ptr instances created from a shared_ptr | ||||
| ``` | ||||
| shared_ptr<X> p1( new X ); | ||||
|  | ||||
| local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1 | ||||
| local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1 | ||||
| ``` | ||||
|  | ||||
| Creating the second `local_shared_ptr` from the first one, however, does lead to the two sharing the same count: | ||||
|  | ||||
| .A local_shared_ptr created from another local_shared_ptr | ||||
| ``` | ||||
| shared_ptr<X> p1( new X ); | ||||
|  | ||||
| local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1 | ||||
| local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2 | ||||
| ``` | ||||
|  | ||||
| Two `shared_ptr` instances created from the same `local_shared_ptr` do share ownership: | ||||
|  | ||||
| .Two shared_ptr instances created from a local_shared_ptr | ||||
| ``` | ||||
| local_shared_ptr<X> p1( new X ); | ||||
|  | ||||
| shared_ptr<X> p2( p1 ); // p2.use_count() == 2 | ||||
| shared_ptr<X> p3( p1 ); // p3.use_count() == 3 | ||||
| ``` | ||||
|  | ||||
| Here `p2.use_count()` is 2, because `p1` holds a reference, too. | ||||
|  | ||||
| One can think of `local_shared_ptr<T>` as `shared_ptr<shared_ptr<T>>`, with the outer `shared_ptr` using non-atomic operations for | ||||
| its count. Converting from `local_shared_ptr` to `shared_ptr` gives you a copy of the inner `shared_ptr`; converting from `shared_ptr` | ||||
| wraps it into an outer `shared_ptr` with a non-atomic use count (conceptually speaking) and returns the result. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `local_shared_ptr` is defined in `<boost/smart_ptr/local_shared_ptr.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class local_shared_ptr { | ||||
|   public: | ||||
|  | ||||
|     typedef /*see below*/ element_type; | ||||
|  | ||||
|     // constructors | ||||
|  | ||||
|     constexpr local_shared_ptr() noexcept; | ||||
|     constexpr local_shared_ptr(std::nullptr_t) noexcept; | ||||
|  | ||||
|     template<class Y> explicit local_shared_ptr(Y * p); | ||||
|  | ||||
|     template<class Y, class D> local_shared_ptr(Y * p, D d); | ||||
|     template<class D> local_shared_ptr(std::nullptr_t p, D d); | ||||
|  | ||||
|     template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a); | ||||
|     template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a); | ||||
|  | ||||
|     local_shared_ptr(local_shared_ptr const & r) noexcept; | ||||
|     template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept; | ||||
|  | ||||
|     local_shared_ptr(local_shared_ptr && r) noexcept; | ||||
|     template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept; | ||||
|  | ||||
|     template<class Y> local_shared_ptr( shared_ptr<Y> const & r ); | ||||
|     template<class Y> local_shared_ptr( shared_ptr<Y> && r ); | ||||
|  | ||||
|     template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept; | ||||
|     template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept; | ||||
|  | ||||
|     template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r); | ||||
|      | ||||
|     // destructor | ||||
|  | ||||
|     ~local_shared_ptr() noexcept; | ||||
|  | ||||
|     // assignment | ||||
|  | ||||
|     local_shared_ptr & operator=(local_shared_ptr const & r) noexcept; | ||||
|     template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept; | ||||
|  | ||||
|     local_shared_ptr & operator=(local_shared_ptr const && r) noexcept; | ||||
|     template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept; | ||||
|  | ||||
|     template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r); | ||||
|  | ||||
|     local_shared_ptr & operator=(std::nullptr_t) noexcept; | ||||
|  | ||||
|     // reset | ||||
| 	 | ||||
|     void reset() noexcept; | ||||
|  | ||||
|     template<class Y> void reset(Y * p); | ||||
|     template<class Y, class D> void reset(Y * p, D d); | ||||
|     template<class Y, class D, class A> void reset(Y * p, D d, A a); | ||||
|  | ||||
|     template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept; | ||||
|     template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept; | ||||
|  | ||||
|     // accessors | ||||
|  | ||||
|     T & operator*() const noexcept; // only valid when T is not an array type | ||||
|     T * operator->() const noexcept; // only valid when T is not an array type | ||||
|  | ||||
|     // only valid when T is an array type | ||||
|     element_type & operator[](std::ptrdiff_t i) const noexcept; | ||||
|  | ||||
|     element_type * get() const noexcept; | ||||
|  | ||||
|     long local_use_count() const noexcept; | ||||
|  | ||||
|     // conversions | ||||
|  | ||||
|     explicit operator bool() const noexcept; | ||||
|  | ||||
|     template<class Y> operator shared_ptr<Y>() const noexcept; | ||||
|     template<class Y> operator weak_ptr<Y>() const noexcept; | ||||
|  | ||||
|     // swap | ||||
|  | ||||
|     void swap(local_shared_ptr & b) noexcept; | ||||
|  | ||||
|     // owner_before | ||||
|  | ||||
|     template<class Y> bool owner_before(local_shared_ptr<Y> const & r) const noexcept; | ||||
|  | ||||
|     // owner_equals | ||||
|  | ||||
|     template<class Y> bool owner_equals(local_shared_ptr<Y> const & r) const noexcept; | ||||
|   }; | ||||
|  | ||||
|   // comparisons | ||||
|    | ||||
|   template<class T, class U> | ||||
|     bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
|   template<class T, class U> | ||||
|     bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; | ||||
|   template<class T, class U> | ||||
|     bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
|   template<class T, class U> | ||||
|     bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; | ||||
|   template<class T, class U> | ||||
|     bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept; | ||||
|   template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept; | ||||
|  | ||||
|   template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept; | ||||
|   template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   // swap | ||||
|    | ||||
|   template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept; | ||||
|  | ||||
|   // get_pointer | ||||
|    | ||||
|   template<class T> | ||||
|     typename local_shared_ptr<T>::element_type * | ||||
|       get_pointer(local_shared_ptr<T> const & p) noexcept; | ||||
|  | ||||
|   // casts | ||||
|    | ||||
|   template<class T, class U> | ||||
|     local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
|  | ||||
|   // stream I/O | ||||
|  | ||||
|   template<class E, class T, class Y> | ||||
|     std::basic_ostream<E, T> & | ||||
|       operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p); | ||||
|  | ||||
|   // get_deleter | ||||
|    | ||||
|   template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### element_type | ||||
| ``` | ||||
| typedef ... element_type; | ||||
| ``` | ||||
| `element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. | ||||
|  | ||||
| ### default constructor | ||||
| ``` | ||||
| constexpr local_shared_ptr() noexcept; | ||||
| ``` | ||||
| ``` | ||||
| constexpr local_shared_ptr(std::nullptr_t) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs an empty `local_shared_ptr`. | ||||
| Postconditions:: `local_use_count() == 0 && get() == 0`. | ||||
|  | ||||
| ### pointer constructor | ||||
| ``` | ||||
| template<class Y> explicit local_shared_ptr(Y * p); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p )`. | ||||
|  | ||||
| Postconditions:: `local_use_count() == 1 && get() == p`. | ||||
|  | ||||
| Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. | ||||
|  | ||||
| ### constructors taking a deleter | ||||
| ``` | ||||
| template<class Y, class D> local_shared_ptr(Y * p, D d); | ||||
| ``` | ||||
| ``` | ||||
| template<class D> local_shared_ptr(std::nullptr_t p, D d); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d )`. | ||||
|  | ||||
| Postconditions:: `local_use_count() == 1 && get() == p`. | ||||
|  | ||||
| Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. | ||||
|  | ||||
| ``` | ||||
| template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a); | ||||
| ``` | ||||
| ``` | ||||
| template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d, a )`. | ||||
|  | ||||
| Postconditions:: `local_use_count() == 1 && get() == p`. | ||||
|  | ||||
| Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. | ||||
|  | ||||
| ### copy and converting constructors | ||||
| ``` | ||||
| local_shared_ptr(local_shared_ptr const & r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `Y*` should be convertible to `T*`. | ||||
|  | ||||
| Effects:: If `r` is empty, constructs an empty `local_shared_ptr`; otherwise, constructs a `local_shared_ptr` that shares ownership with `r`. | ||||
|  | ||||
| Postconditions:: `get() == r.get() && local_use_count() == r.local_use_count()`. | ||||
|  | ||||
| ### move constructors | ||||
| ``` | ||||
| local_shared_ptr(local_shared_ptr && r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `Y*` should be convertible to `T*`. | ||||
|  | ||||
| Effects:: Move-constructs a `local_shared_ptr` from `r`. | ||||
|  | ||||
| Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`. | ||||
|  | ||||
| ### shared_ptr constructor | ||||
| ``` | ||||
| template<class Y> local_shared_ptr( shared_ptr<Y> const & r ); | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> local_shared_ptr( shared_ptr<Y> && r ); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `local_shared_ptr` that owns `r`. | ||||
|  | ||||
| Postconditions:: `local_use_count() == 1`. `get()` returns the old value of `r.get()`. | ||||
|  | ||||
| Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. | ||||
|  | ||||
| ### aliasing constructor | ||||
| ``` | ||||
| template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: constructs a `local_shared_ptr` that shares ownership with `r` and stores `p`. | ||||
|  | ||||
| Postconditions:: `get() == p && local_use_count() == r.local_use_count()`. | ||||
|  | ||||
| ### aliasing move constructor | ||||
| ``` | ||||
| template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Move-constructs a `local_shared_ptr` from `r`, while storing `p` instead. | ||||
|  | ||||
| Postconditions:: `get() == p` and `local_use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`. | ||||
|  | ||||
| ### unique_ptr constructor | ||||
| ``` | ||||
| template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `Y*` should be convertible to `T*`. | ||||
|  | ||||
| Effects:: | ||||
| - When `r.get() == 0`, equivalent to `local_shared_ptr()`; | ||||
| - Otherwise, constructs a `local_shared_ptr` that owns `shared_ptr<T>( std::move(r) )`. | ||||
|  | ||||
| Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. | ||||
|  | ||||
| Exception safety:: If an exception is thrown, the constructor has no effect. | ||||
|  | ||||
| ### destructor | ||||
| ``` | ||||
| ~local_shared_ptr() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
| - If `*this` is empty, or shares ownership with another `local_shared_ptr` instance (`local_use_count() > 1`), there are no side effects. | ||||
| - Otherwise, destroys the owned `shared_ptr`. | ||||
|  | ||||
| ### assignment | ||||
| ``` | ||||
| local_shared_ptr & operator=(local_shared_ptr const & r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr(r).swap(*this)`. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ``` | ||||
| local_shared_ptr & operator=(local_shared_ptr && r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr(std::move(r)).swap(*this)`. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ``` | ||||
| local_shared_ptr & operator=(std::nullptr_t) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr().swap(*this)`. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ### reset | ||||
| ``` | ||||
| void reset() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr().swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| template<class Y> void reset(Y * p); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr(p).swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| template<class Y, class D> void reset(Y * p, D d); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr(p, d).swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| template<class Y, class D, class A> void reset(Y * p, D d, A a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr(p, d, a).swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `local_shared_ptr(r, p).swap(*this)`. | ||||
|  | ||||
| ``` | ||||
| template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Equivalent to `local_shared_ptr(std::move(r), p).swap(*this)`. | ||||
|  | ||||
| ### indirection | ||||
| ``` | ||||
| T & operator*() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `T` should not be an array type. | ||||
| Returns:: `*get()`. | ||||
|  | ||||
| ``` | ||||
| T * operator->() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `T` should not be an array type. | ||||
| Returns:: `get()`. | ||||
|  | ||||
| ``` | ||||
| element_type & operator[](std::ptrdiff_t i) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `T` should be an array type. The stored pointer must not be 0. `i >= 0`. If `T` is `U[N]`, `i < N`. | ||||
| Returns:: `get()[i]`. | ||||
|  | ||||
| ### get | ||||
|  | ||||
| ``` | ||||
| element_type * get() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   The stored pointer. | ||||
|  | ||||
| ### local_use_count | ||||
| ``` | ||||
| long local_use_count() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   The number of `local_shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. | ||||
|  | ||||
| ### conversions | ||||
| ``` | ||||
| explicit operator bool() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `get() != 0`. | ||||
|  | ||||
| NOTE: On C++03 compilers, the return value is of an unspecified type. | ||||
|  | ||||
| ``` | ||||
| template<class Y> operator shared_ptr<Y>() const noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> operator weak_ptr<Y>() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: `T*` should be convertible to `Y*`. | ||||
| Returns:: a copy of the owned `shared_ptr`. | ||||
|  | ||||
| ### swap | ||||
| ``` | ||||
| void swap(local_shared_ptr & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Exchanges the contents of the two smart pointers. | ||||
|  | ||||
| ### owner_before | ||||
| ``` | ||||
| template<class Y> bool owner_before(local_shared_ptr<Y> const & r) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   See the description of `operator<`. | ||||
|  | ||||
| ### owner_equals | ||||
| ``` | ||||
| template<class Y> bool owner_equals(local_shared_ptr<Y> const & r) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `true` if and only if `*this` and `r` share ownership or are both empty. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### comparison | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.get() == b.get()`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.get() != b.get()`. | ||||
|  | ||||
| ``` | ||||
| template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `p.get() == 0`. | ||||
|  | ||||
| ``` | ||||
| template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `p.get() != 0`. | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: An unspecified value such that | ||||
|   - `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; | ||||
|   - under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `local_shared_ptr` instances | ||||
|     are equivalent if and only if they share ownership or are both empty. | ||||
|  | ||||
| NOTE: Allows `local_shared_ptr` objects to be used as keys in associative containers. | ||||
|  | ||||
| NOTE: The rest of the comparison operators are omitted by design. | ||||
|  | ||||
| ### swap | ||||
| ``` | ||||
| template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Equivalent to `a.swap(b)`. | ||||
|  | ||||
| ### get_pointer | ||||
| ``` | ||||
| template<class T> | ||||
|   typename local_shared_ptr<T>::element_type * | ||||
|     get_pointer(local_shared_ptr<T> const & p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `p.get()`. | ||||
|  | ||||
| NOTE: Provided as an aid to generic programming. Used by `mem_fn`. | ||||
|  | ||||
| ### static_pointer_cast | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `static_cast<T*>( (U*)0 )` must be well-formed. | ||||
| Returns:: `local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`. | ||||
|  | ||||
| CAUTION: The seemingly equivalent expression `local_shared_ptr<T>(static_cast<T*>(r.get()))` will eventually | ||||
| result in undefined behavior, attempting to delete the same object twice. | ||||
|  | ||||
| ### const_pointer_cast | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `const_cast<T*>( (U*)0 )` must be well-formed. | ||||
| Returns:: `local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`. | ||||
|  | ||||
| ### dynamic_pointer_cast | ||||
| ``` | ||||
| template<class T, class U> | ||||
|     local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `dynamic_cast<T*>( (U*)0 )` must be well-formed. | ||||
| Returns:: | ||||
|   - When `dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get())` returns a nonzero value `p`, `local_shared_ptr<T>(r, p)`; | ||||
|   - Otherwise, `local_shared_ptr<T>()`. | ||||
|  | ||||
| ### reinterpret_pointer_cast | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `reinterpret_cast<T*>( (U*)0 )` must be well-formed. | ||||
| Returns:: `local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`. | ||||
|  | ||||
| ### operator<< | ||||
| ``` | ||||
| template<class E, class T, class Y> | ||||
|   std::basic_ostream<E, T> & | ||||
|     operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: `os << p.get();`. | ||||
| Returns:: `os`. | ||||
|  | ||||
| ### get_deleter | ||||
| ``` | ||||
| template<class D, class T> | ||||
|   D * get_deleter(local_shared_ptr<T> const & p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0. | ||||
							
								
								
									
										81
									
								
								doc/smart_ptr/make_local_shared.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								doc/smart_ptr/make_local_shared.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| //// | ||||
| Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#make_local_shared] | ||||
| # make_local_shared: Creating local_shared_ptr | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: make_local_shared_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The function templates `make_local_shared` and `allocate_local_shared` provide | ||||
| convenient, safe and efficient ways to create `local_shared_ptr` objects. They | ||||
| are analogous to `make_shared` and `allocate_shared` for `shared_ptr`. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `make_local_shared` and `allocate_local_shared` are defined in | ||||
| `<boost/smart_ptr/make_local_shared.hpp>`. | ||||
|  | ||||
| [subs=+quotes] | ||||
| ``` | ||||
| namespace boost { | ||||
|   `// T is not an array` | ||||
|   template<class T, class... Args> | ||||
|     local_shared_ptr<T> make_local_shared(Args&&... args); | ||||
|   template<class T, class A, class... Args> | ||||
|     local_shared_ptr<T> allocate_local_shared(const A& a, Args&&... args); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     local_shared_ptr<T> make_local_shared(std::size_t n); | ||||
|   template<class T, class A> | ||||
|     local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T> | ||||
|     local_shared_ptr<T> make_local_shared(); | ||||
|   template<class T, class A> | ||||
|     local_shared_ptr<T> allocate_local_shared(const A& a); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     local_shared_ptr<T> make_local_shared(std::size_t n, | ||||
|       const remove_extent_t<T>& v); | ||||
|   template<class T, class A> | ||||
|     local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n, | ||||
|       const remove_extent_t<T>& v); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T> | ||||
|     local_shared_ptr<T> make_local_shared(const remove_extent_t<T>& v); | ||||
|   template<class T, class A> | ||||
|     local_shared_ptr<T> allocate_local_shared(const A& a, | ||||
|       const remove_extent_t<T>& v); | ||||
|  | ||||
|   `// T is not an array of known bounds` | ||||
|   template<class T> | ||||
|     local_shared_ptr<T> make_local_shared_noinit(); | ||||
|   template<class T, class A> | ||||
|     local_shared_ptr<T> allocate_local_shared_noinit(const A& a); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     local_shared_ptr<T> make_local_shared_noinit(std::size_t n); | ||||
|   template<class T, class A> | ||||
|     local_shared_ptr<T> allocate_local_shared_noinit(const A& a, | ||||
|       std::size_t n); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The requirements and effects of these functions are the same as `make_shared` | ||||
| and `allocate_shared`, except that a `local_shared_ptr` is returned. | ||||
							
								
								
									
										296
									
								
								doc/smart_ptr/make_shared.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								doc/smart_ptr/make_shared.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
| Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#make_shared] | ||||
| # make_shared: Creating shared_ptr | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: make_shared_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The function templates `make_shared` and `allocate_shared` provide convenient, | ||||
| safe and efficient ways to create `shared_ptr` objects. | ||||
|  | ||||
| ## Rationale | ||||
|  | ||||
| Consistent use of `shared_ptr` can eliminate the need to use an explicit | ||||
| `delete`, but alone it provides no support in avoiding explicit `new`. There | ||||
| were repeated requests from users for a factory function that creates an | ||||
| object of a given type and returns a `shared_ptr` to it. Besides convenience | ||||
| and style, such a function is also exception safe and considerably faster | ||||
| because it can use a single allocation for both the object and its | ||||
| corresponding control block, eliminating a significant portion of | ||||
| `shared_ptr` construction overhead. This eliminates one of the major | ||||
| efficiency complaints about `shared_ptr`. | ||||
|  | ||||
| The family of overloaded function templates, `make_shared` and | ||||
| `allocate_shared`, were provided to address this need. `make_shared` uses the | ||||
| global `operator new` to allocate memory, whereas `allocate_shared` uses an | ||||
| user-supplied allocator, allowing finer control. | ||||
|  | ||||
| The rationale for choosing the name `make_shared` is that the expression | ||||
| `make_shared<Widget>()` can be read aloud and conveys the intended meaning. | ||||
|  | ||||
| Originally the Boost function templates `allocate_shared` and `make_shared` | ||||
| were provided for scalar objects only. There was a need to have efficient | ||||
| allocation of array objects. One criticism of class template `shared_array` | ||||
| was always the lack of a utility like `make_shared` that uses only a single | ||||
| allocation. When `shared_ptr` was enhanced to support array types, additional | ||||
| overloads of `allocate_shared` and `make_shared` were provided for array | ||||
| types. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `make_shared` and `allocate_shared` are defined in | ||||
| `<boost/smart_ptr/make_shared.hpp>`. | ||||
|  | ||||
| [subs=+quotes] | ||||
| ``` | ||||
| namespace boost { | ||||
|   `// T is not an array` | ||||
|   template<class T, class... Args> | ||||
|     shared_ptr<T> make_shared(Args&&... args); | ||||
|   template<class T, class A, class... Args> | ||||
|     shared_ptr<T> allocate_shared(const A& a, Args&&... args); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     shared_ptr<T> make_shared(std::size_t n); | ||||
|   template<class T, class A> | ||||
|     shared_ptr<T> allocate_shared(const A& a, std::size_t n); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T> | ||||
|     shared_ptr<T> make_shared(); | ||||
|   template<class T, class A> | ||||
|     shared_ptr<T> allocate_shared(const A& a); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> shared_ptr<T> | ||||
|     make_shared(std::size_t n, const remove_extent_t<T>& v); | ||||
|   template<class T, class A> shared_ptr<T> | ||||
|     allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v); | ||||
|  | ||||
|   `// T is an array of known bounds` | ||||
|   template<class T> | ||||
|     shared_ptr<T> make_shared(const remove_extent_t<T>& v); | ||||
|   template<class T, class A> | ||||
|     shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v); | ||||
|  | ||||
|   `// T is not an array of unknown bounds` | ||||
|   template<class T> | ||||
|     shared_ptr<T> make_shared_noinit(); | ||||
|   template<class T, class A> | ||||
|     shared_ptr<T> allocate_shared_noinit(const A& a); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     shared_ptr<T> make_shared_noinit(std::size_t n); | ||||
|   template<class T, class A> | ||||
|     shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Common Requirements | ||||
|  | ||||
| The common requirements that apply to all `make_shared` and `allocate_shared` | ||||
| overloads, unless specified otherwise, are described below. | ||||
|  | ||||
| Requires:: `A` shall be an _allocator_. The copy constructor and destructor | ||||
| of `A` shall not throw exceptions. | ||||
|  | ||||
| Effects:: Allocates memory for an object of type `T`  or `n` objects of `U` | ||||
| (if `T` is an array type of the form `U[]` and  `n` is determined by | ||||
| arguments, as specified by the concrete overload). The object is initialized | ||||
| from arguments as specified by the concrete overload. Uses a rebound copy of | ||||
| `a` (for an unspecified `value_type`) to allocate memory. If an exception is | ||||
| thrown, the functions have no effect. | ||||
|  | ||||
| Returns:: A `shared_ptr` instance that stores and owns the address of the | ||||
| newly constructed object. | ||||
|  | ||||
| Postconditions:: `r.get() != 0` and `r.use_count() == 1`, where `r` | ||||
| is the return value. | ||||
|  | ||||
| Throws:: `std::bad_alloc`, an exception thrown from `A::allocate`, or from the | ||||
| initialization of the object. | ||||
|  | ||||
| Remarks:: | ||||
| * Performs no more than one memory allocation. This provides efficiency | ||||
| equivalent to an intrusive smart pointer. | ||||
| * When an object of an array type is specified to be initialized to a value of | ||||
| the same type `v`, this shall be interpreted to mean that each array element | ||||
| of the object is initialized to the corresponding element from `v`. | ||||
| * When an object of an array type is specified to be value-initialized, this | ||||
| shall be interpreted to mean that each array element of the object is | ||||
| value-initialized. | ||||
| * When a (sub)object of non-array type `U` is specified to be initialized to | ||||
| a value `v`, or constructed from `args\...`, `make_shared` shall perform | ||||
| this initialization via the expression `::new(p) U(expr)` (where | ||||
| `_expr_` is `v` or `std::forward<Args>(args)\...)` respectively) and `p` | ||||
| has type `void*` and points to storage suitable to hold an object of type | ||||
| `U`. | ||||
| * When a (sub)object of non-array type `U` is specified to be initialized to | ||||
| a value `v`, or constructed from `args\...`, `allocate_shared` shall | ||||
| perform this initialization via the expression | ||||
| `std::allocator_traits<A2>::construct(a2, p, expr)` (where | ||||
| `_expr_` is `v` or `std::forward<Args>(args)\...)` respectively), `p` | ||||
| points to storage suitable to hold an object of type `U`, and `a2` of | ||||
| type `A2` is a potentially rebound copy of `a`. | ||||
| * When a (sub)object of non-array type `U` is specified to be | ||||
| default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall | ||||
| perform this initialization via the expression `::new(p) U`, where | ||||
| `p` has type `void*` and points to storage suitable to hold an object of | ||||
| type `U`. | ||||
| * When a (sub)object of non-array type `U` is specified to be | ||||
| value-initialized, `make_shared` shall perform this initialization via the | ||||
| expression `::new(p) U()`, where `p` has type `void*` and points to | ||||
| storage suitable to hold an object of type `U`. | ||||
| * When a (sub)object of non-array type `U` is specified to be | ||||
| value-initialized, `allocate_shared` shall perform this initialization via the | ||||
| expression `std::allocator_traits<A2>::construct(a2, p)`, where | ||||
| `p` points to storage suitable to hold an object of type `U` and `a2` of | ||||
| type `A2` is a potentially rebound copy of `a`. | ||||
| * Array elements are initialized in ascending order of their addresses. | ||||
| * When the lifetime of the object managed by the return value ends, or when | ||||
| the initialization of an array element throws an exception, the initialized | ||||
| elements should be destroyed in the reverse order of their construction. | ||||
|  | ||||
| NOTE: These functions will typically allocate more memory than the total size | ||||
| of the element objects to allow for internal bookkeeping structures such as | ||||
| the reference counts. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ``` | ||||
| template<class T, class... Args> | ||||
|   shared_ptr<T> make_shared(Args&&... args); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A, class... Args> | ||||
|   shared_ptr<T> allocate_shared(const A& a, Args&&... args); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: A `shared_ptr` to an object of type `T`, constructed from | ||||
| `args\...`. | ||||
| Examples:: | ||||
| * `auto p = make_shared<int>();` | ||||
| * `auto p = make_shared<std::vector<int> >(16, 1);` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   shared_ptr<T> make_shared(std::size_t n); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   shared_ptr<T> allocate_shared(const A& a, std::size_t n); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of | ||||
| type `remove_extent_t<T>`. | ||||
| Examples:: | ||||
| * `auto p = make_shared<double[]>(1024);` | ||||
| * `auto p = make_shared<double[][2][2]>(6);` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   shared_ptr<T> make_shared(); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   shared_ptr<T> allocate_shared(const A& a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of known bounds. | ||||
| Returns:: A `shared_ptr` to a sequence of `extent_v<T>` value-initialized | ||||
| objects of type `remove_extent_t<T>`. | ||||
| Examples:: | ||||
| * `auto p = make_shared<double[1024]>();` | ||||
| * `auto p = make_shared<double[6][2][2]>();` | ||||
|  | ||||
| ``` | ||||
| template<class T> shared_ptr<T> | ||||
|   make_shared(std::size_t n, const remove_extent_t<T>& v); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A> shared_ptr<T> | ||||
|   allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: A `shared_ptr` to a sequence of `n` objects of type | ||||
| `remove_extent_t<T>`, each initialized to `v`. | ||||
| Examples:: | ||||
| * `auto p = make_shared<double[]>(1024, 1.0);` | ||||
| * `auto p = make_shared<double[][2]>(6, {1.0, 0.0});` | ||||
| * `auto p = make_shared<std::vector<int>[]>(4, {1, 2});` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   shared_ptr<T> make_shared(const remove_extent_t<T>& v); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of known bounds. | ||||
| Returns:: A `shared_ptr` to a sequence of `extent_v<T>` objects of type | ||||
| `remove_extent_t<T>`, each initialized to `v`. | ||||
| Examples:: | ||||
| * `auto p = make_shared<double[1024]>(1.0);` | ||||
| * `auto p = make_shared<double[6][2]>({1.0, 0.0});` | ||||
| * `auto p = make_shared<std::vector<int>[4]>({1, 2});` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   shared_ptr<T> make_shared_noinit(); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   shared_ptr<T> allocate_shared_noinit(const A& a); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array, or is an array of known bounds. | ||||
| Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a | ||||
| sequence of `extent_v<T>` default-initialized objects of type | ||||
| `remove_extent_t<T>`, respectively. | ||||
| Example:: `auto p = make_shared_noinit<double[1024]>();` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   shared_ptr<T> make_shared_noinit(std::size_t n); | ||||
| ``` | ||||
| ``` | ||||
| template<class T, class A> | ||||
|   shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects | ||||
| of type `remove_extent_t<T>`. | ||||
| Example:: `auto p = make_shared_noinit<double[]>(1024);` | ||||
							
								
								
									
										120
									
								
								doc/smart_ptr/make_unique.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								doc/smart_ptr/make_unique.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
| Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#make_unique] | ||||
| # make_unique: Creating unique_ptr | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: make_unique_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `make_unique` function templates provide convenient and safe ways to | ||||
| create `std::unique_ptr` objects. | ||||
|  | ||||
| ## Rationale | ||||
|  | ||||
| The {cpp}11 standard introduced `std::unique_ptr` but did not provide any | ||||
| `make_unique` utility like `std::make_shared` that provided the same | ||||
| exception safety and facility to avoid writing `new` expressions. Before it | ||||
| was implemented by some standard library vendors (and prior to the {cpp}14 | ||||
| standard introducing `std::make_unique`), this library provided it due to | ||||
| requests from users. | ||||
|  | ||||
| This library also provides additional overloads of `make_unique` for | ||||
| default-initialization, when users do not need or want to incur the expense | ||||
| of value-initialization. The {cpp}20 standard now provides this feature with | ||||
| `std::make_unique_for_overwrite`. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `make_unique` is defined in `<boost/smart_ptr/make_unique.hpp>`. | ||||
|  | ||||
| [subs=+quotes] | ||||
| ``` | ||||
| namespace boost { | ||||
|   `// T is not an array` | ||||
|   template<class T, class... Args> | ||||
|     std::unique_ptr<T> make_unique(Args&&... args); | ||||
|  | ||||
|   `// T is not an array` | ||||
|   template<class T> | ||||
|     std::unique_ptr<T> make_unique(type_identity_t<T>&& v); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     std::unique_ptr<T> make_unique(std::size_t n); | ||||
|  | ||||
|   `// T is not an array` | ||||
|   template<class T> | ||||
|     std::unique_ptr<T> make_unique_noinit(); | ||||
|  | ||||
|   `// T is an array of unknown bounds` | ||||
|   template<class T> | ||||
|     std::unique_ptr<T> make_unique_noinit(std::size_t n); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ``` | ||||
| template<class T, class... Args> | ||||
|   std::unique_ptr<T> make_unique(Args&&... args); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`. | ||||
| Example:: `auto p = make_unique<int>();` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   std::unique_ptr<T> make_unique(type_identity_t<T>&& v); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: `std::unique_ptr<T>(new T(std::move(v))`. | ||||
| Example:: `auto p = make_unique<std::vector<int> >({1, 2});` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   std::unique_ptr<T> make_unique(std::size_t n); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: `std::unique_ptr<T>(new remove_extent_t<T>[n]())`. | ||||
| Example:: `auto p = make_unique<double[]>(1024);` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   std::unique_ptr<T> make_unique_noinit(); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is not an array. | ||||
| Returns:: `std::unique_ptr<T>(new T)`. | ||||
| Example:: `auto p = make_unique_noinit<std::array<double, 1024> >();` | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   std::unique_ptr<T> make_unique_noinit(std::size_t n); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Constraints:: `T` is an array of unknown bounds. | ||||
| Returns:: `std::unique_ptr<T>(new remove_extent_t<T>[n])`. | ||||
| Example:: `auto p = make_unique_noinit<double[]>(1024);` | ||||
							
								
								
									
										45
									
								
								doc/smart_ptr/owner_equal_to.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								doc/smart_ptr/owner_equal_to.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| //// | ||||
| Copyright 2020 Peter Dimov | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| https://www.boost.org/LICENSE_1_0.txt | ||||
| //// | ||||
|  | ||||
| [#owner_equal_to] | ||||
| # owner_equal_to | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: owner_equal_to_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| `owner_equal_to<T>` is a helper function object that compares two smart | ||||
| pointer objects using `owner_equals`. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `owner_equal_to` is defined in `<boost/smart_ptr/owner_equal_to.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T = void> struct owner_equal_to | ||||
|   { | ||||
|     typedef bool result_type; | ||||
|     typedef T first_argument_type; | ||||
|     typedef T second_argument_type; | ||||
|  | ||||
|     template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept; | ||||
|   }; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ``` | ||||
| template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `u.owner_equals( v )`. | ||||
							
								
								
									
										56
									
								
								doc/smart_ptr/owner_hash.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								doc/smart_ptr/owner_hash.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| //// | ||||
| Copyright 2020 Peter Dimov | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| https://www.boost.org/LICENSE_1_0.txt | ||||
| //// | ||||
|  | ||||
| [#owner_hash] | ||||
| # owner_hash | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: owner_hash_to_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| `owner_hash<T>` is a helper function object that takes a smart pointer `p` | ||||
| and returns `p.owner_hash_value()`. It's useful for creating unordered | ||||
| containers of `shared_ptr` that use ownership-based equality, instead of | ||||
| the default pointer value equality. (It can be used with `weak_ptr` too, | ||||
| but there's no need, because `boost::hash` and `std::hash` for `weak_ptr` | ||||
| already use ownership-based equality.) | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| ``` | ||||
| std::unordered_set< boost::shared_ptr<void>, | ||||
|   boost::owner_hash< boost::shared_ptr<void> >, | ||||
|   boost::owner_equal_to< boost::shared_ptr<void> > > set; | ||||
| ``` | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `owner_hash` is defined in `<boost/smart_ptr/owner_hash.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> struct owner_hash | ||||
|   { | ||||
|     typedef std::size_t result_type; | ||||
|     typedef T argument_type; | ||||
|  | ||||
|     std::size_t operator()( T const & p ) const noexcept; | ||||
|   }; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ``` | ||||
| std::size_t operator()( T const & p ) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `p.owner_hash_value()`. | ||||
							
								
								
									
										50
									
								
								doc/smart_ptr/owner_less.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								doc/smart_ptr/owner_less.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| //// | ||||
| Copyright 2020 Peter Dimov | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| https://www.boost.org/LICENSE_1_0.txt | ||||
| //// | ||||
|  | ||||
| [#owner_less] | ||||
| # owner_less | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: owner_less_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| `owner_less<T>` is a helper function object that compares two smart | ||||
| pointer objects using `owner_before`. It is only provided for compatibility | ||||
| with {cpp}11 and corresponds to the standard component of the same name. | ||||
|  | ||||
| When using Boost smart pointers, the use of `owner_less` is unnecessary, as | ||||
| the supplied `operator<` overloads (and, correspondingly, `std::less`) return | ||||
| the same result. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `owner_less` is defined in `<boost/smart_ptr/owner_less.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T = void> struct owner_less | ||||
|   { | ||||
|     typedef bool result_type; | ||||
|     typedef T first_argument_type; | ||||
|     typedef T second_argument_type; | ||||
|  | ||||
|     template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept; | ||||
|   }; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ``` | ||||
| template<class U, class V> bool operator()( U const & u, V const & v ) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `u.owner_before( v )`. | ||||
							
								
								
									
										237
									
								
								doc/smart_ptr/pointer_cast.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										237
									
								
								doc/smart_ptr/pointer_cast.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,237 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#pointer_cast] | ||||
| # Generic Pointer Casts | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: pointer_cast_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The pointer cast function templates (`static_pointer_cast`, | ||||
| `dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`) | ||||
| provide a way to write generic pointer castings for raw pointers, | ||||
| `std::shared_ptr` and `std::unique_ptr`. | ||||
|  | ||||
| There is test and example code in | ||||
| link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp] | ||||
|  | ||||
| ## Rationale | ||||
|  | ||||
| Boost smart pointers usually overload those functions to provide a mechanism | ||||
| to emulate pointers casts. For example, `shared_ptr<T>` implements a static | ||||
| pointer cast this way: | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p); | ||||
| ``` | ||||
|  | ||||
| Pointer cast functions templates are overloads of `static_pointer_cast`, | ||||
| `dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast` | ||||
| for raw pointers, `std::shared_ptr` and `std::unique_ptr`. This way when | ||||
| developing pointer type independent classes, for example, memory managers or | ||||
| shared memory compatible classes, the same code can be used for raw and smart | ||||
| pointers. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| The generic pointer casts are defined in `<boost/pointer_cast.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|   template<class T, class U> T* static_pointer_cast(U* p) noexcept; | ||||
|   template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept; | ||||
|   template<class T, class U> T* const_pointer_cast(U* p) noexcept; | ||||
|   template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept; | ||||
|  | ||||
|   template<class T, class U> std::shared_ptr<T> | ||||
|     static_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
|   template<class T, class U> std::shared_ptr<T> | ||||
|     dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
|   template<class T, class U> std::shared_ptr<T> | ||||
|     const_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
|   template<class T, class U> std::shared_ptr<T> | ||||
|     reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
|  | ||||
|   template<class T, class U> std::unique_ptr<T> | ||||
|     static_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
|   template<class T, class U> std::unique_ptr<T> | ||||
|     dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
|   template<class T, class U> std::unique_ptr<T> | ||||
|     const_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
|   template<class T, class U> std::unique_ptr<T> | ||||
|     reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### static_pointer_cast | ||||
| ``` | ||||
| template<class T, class U> T* static_pointer_cast(U* p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `static_cast<T*>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::shared_ptr<T> | ||||
|   static_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `std::static_pointer_cast<T>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::unique_ptr<T> | ||||
|   static_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `static_cast<T*>((U*)0)` must be well-formed. | ||||
| Returns:: `std::unique_ptr<T>(static_cast<typename | ||||
| std::unique_ptr<T>::element_type*>(p.release()))`. | ||||
|  | ||||
| CAUTION: The seemingly equivalent expression | ||||
| `std::unique_ptr<T>(static_cast<T*>(p.get()))` will eventually result in | ||||
| undefined behavior, attempting to delete the same object twice. | ||||
|  | ||||
| ### dynamic_pointer_cast | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `dynamic_cast<T*>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::shared_ptr<T> | ||||
|   dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `std::dynamic_pointer_cast<T>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::unique_ptr<T> | ||||
|   dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: | ||||
| * The expression `static_cast<T*>((U*)0)` must be well-formed. | ||||
| * `T` must have a virtual destructor. | ||||
| Returns:: | ||||
| * When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())` | ||||
| returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename | ||||
| std::unique_ptr<T>::element_type*>(p.release()));`. | ||||
| * Otherwise, `std::unique_ptr<T>()`. | ||||
|  | ||||
| ### const_pointer_cast | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> T* const_pointer_cast(U* p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `const_cast<T*>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::shared_ptr<T> | ||||
|   const_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `std::const_pointer_cast<T>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::unique_ptr<T> | ||||
|   const_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `const_cast<T*>((U*)0)` must be well-formed. | ||||
| Returns:: `std::unique_ptr<T>(const_cast<typename | ||||
| std::unique_ptr<T>::element_type*>(p.release()))`. | ||||
|  | ||||
| ### reinterpret_pointer_cast | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `reinterpret_cast<T*>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::shared_ptr<T> | ||||
|   reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `std::reinterpret_pointer_cast<T>(p)` | ||||
|  | ||||
| ``` | ||||
| template<class T, class U> std::unique_ptr<T> | ||||
|   reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Requires:: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed. | ||||
| Returns:: `std::unique_ptr<T>(reinterpret_cast<typename | ||||
| std::unique_ptr<T>::element_type*>(p.release()))`. | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| The following example demonstrates how the generic pointer casts help us | ||||
| create pointer independent code. | ||||
|  | ||||
| ``` | ||||
| #include <boost/pointer_cast.hpp> | ||||
| #include <boost/shared_ptr.hpp> | ||||
|  | ||||
| class base { | ||||
| public: | ||||
|   virtual ~base() { } | ||||
| }; | ||||
|  | ||||
| class derived : public base { }; | ||||
|  | ||||
| template<class Ptr> | ||||
| void check_if_it_is_derived(const Ptr& ptr) | ||||
| { | ||||
|   assert(boost::dynamic_pointer_cast<derived>(ptr) != 0); | ||||
| } | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   base* ptr = new derived; | ||||
|   boost::shared_ptr<base> sptr(new derived); | ||||
|  | ||||
|   check_if_it_is_derived(ptr); | ||||
|   check_if_it_is_derived(sptr); | ||||
|  | ||||
|   delete ptr; | ||||
| } | ||||
| ``` | ||||
							
								
								
									
										114
									
								
								doc/smart_ptr/pointer_to_other.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								doc/smart_ptr/pointer_to_other.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| //// | ||||
| Copyright 2005, 2006 Ion Gaztañaga | ||||
| Copyright 2005, 2006, 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#pointer_to_other] | ||||
| # pointer_to_other | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: pointer_to_other_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `pointer_to_other` utility provides a way, given a source pointer type, to obtain a pointer of the same type | ||||
| to another pointee type. | ||||
|  | ||||
| There is test/example code in link:../../test/pointer_to_other_test.cpp[pointer_to_other_test.cpp]. | ||||
|  | ||||
| ## Rationale | ||||
|  | ||||
| When building pointer independent classes, like memory managers, allocators, or containers, there is often a need to | ||||
| define pointers generically, so that if a template parameter represents a pointer (for example, a raw or smart pointer | ||||
| to an `int`), we can define another pointer of the same type to another pointee (a raw or smart pointer to a `float`.) | ||||
|  | ||||
| ``` | ||||
| template <class IntPtr> class FloatPointerHolder | ||||
| { | ||||
|     // Let's define a pointer to a float | ||||
|  | ||||
|     typedef typename boost::pointer_to_other | ||||
|         <IntPtr, float>::type float_ptr_t; | ||||
|  | ||||
|     float_ptr_t float_ptr; | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `pointer_to_other` is defined in `<boost/smart_ptr/pointer_to_other.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T, class U> struct pointer_to_other; | ||||
|  | ||||
|   template<class T, class U, | ||||
|     template <class> class Sp> | ||||
|       struct pointer_to_other< Sp<T>, U > | ||||
|   { | ||||
|     typedef Sp<U> type; | ||||
|   }; | ||||
|  | ||||
|   template<class T, class T2, class U, | ||||
|     template <class, class> class Sp> | ||||
|       struct pointer_to_other< Sp<T, T2>, U > | ||||
|   { | ||||
|     typedef Sp<U, T2> type; | ||||
|   }; | ||||
|  | ||||
|   template<class T, class T2, class T3, class U, | ||||
|     template <class, class, class> class Sp> | ||||
|       struct pointer_to_other< Sp<T, T2, T3>, U > | ||||
|   { | ||||
|     typedef Sp<U, T2, T3> type; | ||||
|   }; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     struct pointer_to_other< T*, U >  | ||||
|   { | ||||
|     typedef U* type; | ||||
|   }; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| If these definitions are not correct for a specific smart pointer, we can define a specialization of `pointer_to_other`. | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| ``` | ||||
| // Let's define a memory allocator that can | ||||
| // work with raw and smart pointers | ||||
|  | ||||
| #include <boost/pointer_to_other.hpp> | ||||
|  | ||||
| template <class VoidPtr> | ||||
| class memory_allocator | ||||
| { | ||||
|     // Predefine a memory_block | ||||
|  | ||||
|     struct block; | ||||
|  | ||||
|     // Define a pointer to a memory_block from a void pointer | ||||
|     // If VoidPtr is void *, block_ptr_t is block* | ||||
|     // If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block> | ||||
|  | ||||
|     typedef typename boost::pointer_to_other | ||||
|         <VoidPtr, block>::type block_ptr_t; | ||||
|  | ||||
|     struct block | ||||
|     { | ||||
|         std::size_t size; | ||||
|         block_ptr_t next_block; | ||||
|     }; | ||||
|  | ||||
|     block_ptr_t free_blocks; | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| As we can see, using `pointer_to_other` we can create pointer independent code. | ||||
							
								
								
									
										175
									
								
								doc/smart_ptr/scoped_array.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								doc/smart_ptr/scoped_array.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,175 @@ | ||||
| //// | ||||
| Copyright 1999 Greg Colvin and Beman Dawes | ||||
| Copyright 2002 Darin Adler | ||||
| Copyright 2002-2005, 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#scoped_array] | ||||
| # scoped_array: Scoped Array Ownership | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: scoped_array_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `scoped_array` class template stores a pointer to a dynamically allocated array. | ||||
| (Dynamically allocated arrays are allocated with the {cpp} `new[]` expression.) The array | ||||
| pointed to is guaranteed to be deleted, either on destruction of the `scoped_array`, | ||||
| or via an explicit `reset`. | ||||
|  | ||||
| The `scoped_array` template is a simple solution for simple needs. It supplies a basic | ||||
| "resource acquisition is initialization" facility, without shared-ownership or | ||||
| transfer-of-ownership semantics. Both its name and enforcement of semantics | ||||
| (by being  noncopyable) signal its intent to retain ownership solely within the current scope. | ||||
| Because it is noncopyable, it is safer than `shared_ptr<T[]>` for pointers which should not be copied. | ||||
|  | ||||
| Because `scoped_array` is so simple, in its usual implementation every operation is as fast as a | ||||
| built-in array pointer and it has no more space overhead that a built-in array pointer. | ||||
|  | ||||
| It cannot be used in {cpp} standard library containers. See `shared_ptr<T[]>` if `scoped_array` | ||||
| does not meet your needs. | ||||
|  | ||||
| It cannot correctly hold a pointer to a single object. See `scoped_ptr` for that usage. | ||||
|  | ||||
| `std::vector` is an alternative to `scoped_array` that is a bit heavier duty but far more flexible. | ||||
| `boost::array` is an alternative that does not use dynamic allocation. | ||||
|  | ||||
| The class template is parameterized on `T`, the type of the object pointed to. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `scoped_array` is defined in `<boost/smart_ptr/scoped_array.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class scoped_array { | ||||
|   private: | ||||
|  | ||||
|     scoped_array(scoped_array const &); | ||||
|     scoped_array & operator=(scoped_array const &); | ||||
|  | ||||
|     void operator==( scoped_array const& ) const; | ||||
|     void operator!=( scoped_array const& ) const; | ||||
|  | ||||
|   public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     explicit scoped_array(T * p = 0) noexcept; | ||||
|     ~scoped_array() noexcept; | ||||
|  | ||||
|     void reset(T * p = 0) noexcept; | ||||
|  | ||||
|     T & operator[](std::ptrdiff_t i) const noexcept; | ||||
|     T * get() const noexcept; | ||||
|  | ||||
|     explicit operator bool () const noexcept; | ||||
|  | ||||
|     void swap(scoped_array & b) noexcept; | ||||
|   }; | ||||
|  | ||||
|   template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept; | ||||
|  | ||||
|   template<class T> | ||||
|     bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept; | ||||
|   template<class T> | ||||
|     bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept; | ||||
|  | ||||
|   template<class T> | ||||
|     bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept; | ||||
|   template<class T> | ||||
|     bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### element_type | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
| Provides the type of the stored pointer. | ||||
|  | ||||
| ### constructors | ||||
|  | ||||
|     explicit scoped_array(T * p = 0) noexcept; | ||||
|  | ||||
| Constructs a `scoped_array`, storing a copy of `p`, which must have been | ||||
| allocated via a {cpp} `new[]` expression or be 0. `T` is not required be a complete type. | ||||
|  | ||||
| ### destructor | ||||
|  | ||||
|     ~scoped_array() noexcept; | ||||
|  | ||||
| Deletes the array pointed to by the stored pointer. Note that `delete[]` on a pointer with | ||||
| a value of 0 is harmless. `T` must be complete, and `delete[]` on the stored pointer must | ||||
| not throw exceptions. | ||||
|  | ||||
| ### reset | ||||
|  | ||||
|     void reset(T * p = 0) noexcept; | ||||
|  | ||||
| Deletes the array pointed to by the stored pointer and then stores a copy of `p`, | ||||
| which must have been allocated via a {cpp} `new[]` expression or be 0. `T` must be complete, | ||||
| and `delete[]` on the stored pointer must not throw exceptions. | ||||
|  | ||||
| ### subscripting | ||||
|  | ||||
|     T & operator[](std::ptrdiff_t i) const noexcept; | ||||
|  | ||||
| Returns a reference to element `i` of the array pointed to by the stored pointer. | ||||
| Behavior is undefined and almost certainly undesirable if the stored pointer is 0, | ||||
| or if `i` is less than 0 or is greater than or equal to the number of elements in | ||||
| the array. | ||||
|  | ||||
| ### get | ||||
|  | ||||
|     T * get() const noexcept; | ||||
|  | ||||
| Returns the stored pointer. `T` need not be a complete type. | ||||
|  | ||||
| ### conversions | ||||
|  | ||||
|     explicit operator bool () const noexcept; | ||||
|  | ||||
| Returns `get() != 0`. | ||||
|  | ||||
| NOTE: On C++03 compilers, the return value is of an unspecified type. | ||||
|  | ||||
| ### swap | ||||
|  | ||||
|     void swap(scoped_array & b) noexcept; | ||||
|  | ||||
| Exchanges the contents of the two smart pointers. `T` need not be a complete type. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### swap | ||||
|  | ||||
|     template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept; | ||||
|  | ||||
| Equivalent to `a.swap(b)`. | ||||
|  | ||||
| ### comparisons | ||||
|  | ||||
|     template<class T> | ||||
|       bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept; | ||||
|  | ||||
|     template<class T> | ||||
|       bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept; | ||||
|  | ||||
| Returns `p.get() == nullptr`. | ||||
|  | ||||
|     template<class T> | ||||
|       bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept; | ||||
|  | ||||
|     template<class T> | ||||
|       bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept; | ||||
|  | ||||
| Returns `p.get() != nullptr`. | ||||
							
								
								
									
										234
									
								
								doc/smart_ptr/scoped_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								doc/smart_ptr/scoped_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#scoped_ptr] | ||||
| # scoped_ptr: Scoped Object Ownership | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: scoped_ptr_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `scoped_ptr` class template stores a pointer to a dynamically allocated object. | ||||
| (Dynamically allocated objects are allocated with the {cpp} `new` expression.) The | ||||
| object pointed to is guaranteed to be deleted, either on destruction of the `scoped_ptr`, | ||||
| or via an explicit `reset`. See the <<scoped_ptr_example,example>>. | ||||
|  | ||||
| `scoped_ptr` is a simple solution for simple needs. It supplies a basic "resource acquisition | ||||
| is initialization" facility, without shared-ownership or transfer-of-ownership semantics. | ||||
| Both its name and enforcement of semantics (by being  noncopyable) signal its intent to retain | ||||
| ownership solely within the current scope. Because it is noncopyable, it is safer than `shared_ptr` | ||||
| for pointers which should not be copied. | ||||
|  | ||||
| Because `scoped_ptr` is simple, in its usual implementation every operation is as fast as for a | ||||
| built-in pointer and it has no more space overhead that a built-in pointer. | ||||
|  | ||||
| `scoped_ptr` cannot be used in {cpp} Standard Library containers. Use `shared_ptr` or `std::unique_ptr` | ||||
| if you need a smart pointer that can. | ||||
|  | ||||
| `scoped_ptr` cannot correctly hold a pointer to a dynamically allocated array. See `scoped_array` for that usage. | ||||
|  | ||||
| The class template is parameterized on `T`, the type of the object pointed to. Destroying `T` must not thow exceptions, | ||||
| and `T` must be complete at the point `scoped_ptr<T>::~scoped_ptr` is instantiated. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `scoped_ptr` is defined in `<boost/smart_ptr/scoped_ptr.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class scoped_ptr { | ||||
|   private: | ||||
|  | ||||
|     scoped_ptr(scoped_ptr const&); | ||||
|     scoped_ptr& operator=(scoped_ptr const&); | ||||
|  | ||||
|     void operator==(scoped_ptr const&) const; | ||||
|     void operator!=(scoped_ptr const&) const; | ||||
|  | ||||
|   public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     explicit scoped_ptr(T * p = 0) noexcept; | ||||
|     ~scoped_ptr() noexcept; | ||||
|  | ||||
|     void reset(T * p = 0) noexcept; | ||||
|  | ||||
|     T & operator*() const noexcept; | ||||
|     T * operator->() const noexcept; | ||||
|     T * get() const noexcept; | ||||
|  | ||||
|     explicit operator bool() const noexcept; | ||||
|  | ||||
|     void swap(scoped_ptr & b) noexcept; | ||||
|   }; | ||||
|  | ||||
|   template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept; | ||||
|  | ||||
|   template<class T> | ||||
|     bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept; | ||||
|   template<class T> | ||||
|     bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept; | ||||
|  | ||||
|   template<class T> | ||||
|     bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept; | ||||
|   template<class T> | ||||
|     bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### element_type | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
| Provides the type of the stored pointer. | ||||
|  | ||||
| ### constructor | ||||
|  | ||||
|     explicit scoped_ptr(T * p = 0) noexcept; | ||||
|  | ||||
| Constructs a `scoped_ptr`, storing a copy of `p`, which must have been allocated via a | ||||
| {cpp} `new` expression or be 0. `T` is not required be a complete type. | ||||
|  | ||||
| ### destructor | ||||
|  | ||||
|     ~scoped_ptr() noexcept; | ||||
|  | ||||
| Destroys the object pointed to by the stored pointer, if any, as if by using | ||||
| `delete this\->get()`. `T` must be a complete type. | ||||
|  | ||||
| ### reset | ||||
|  | ||||
|     void reset(T * p = 0) noexcept; | ||||
|  | ||||
| Deletes the object pointed to by the stored pointer and then stores a copy of | ||||
| `p`, which must have been allocated via a {cpp} `new` expression or be 0. | ||||
|  | ||||
| Since the previous object needs to be deleted, `T` must be a complete type. | ||||
|  | ||||
| ### indirection | ||||
|  | ||||
|     T & operator*() const noexcept; | ||||
|  | ||||
| Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0. | ||||
|  | ||||
|     T * operator->() const noexcept; | ||||
|  | ||||
| Returns the stored pointer. Behavior is undefined if the stored pointer is 0. | ||||
|  | ||||
| ### get | ||||
|  | ||||
|     T * get() const noexcept; | ||||
|  | ||||
| Returns the stored pointer. `T` need not be a complete type. | ||||
|  | ||||
| ### conversions | ||||
|  | ||||
|     explicit operator bool () const noexcept; // never throws | ||||
|  | ||||
| Returns `get() != 0`. | ||||
|  | ||||
| NOTE: On C++03 compilers, the return value is of an unspecified type. | ||||
|  | ||||
| ### swap | ||||
|  | ||||
|     void swap(scoped_ptr & b) noexcept; | ||||
|  | ||||
| Exchanges the contents of the two smart pointers. `T` need not be a complete type. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### swap | ||||
|  | ||||
|     template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept; | ||||
|  | ||||
| Equivalent to `a.swap(b)`. | ||||
|  | ||||
| ### comparisons | ||||
|  | ||||
|     template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept; | ||||
|  | ||||
|     template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept; | ||||
|  | ||||
| Returns `p.get() == nullptr`. | ||||
|  | ||||
|     template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept; | ||||
|  | ||||
|     template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept; | ||||
|  | ||||
| Returns `p.get() != nullptr`. | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| Here's an example that uses `scoped_ptr`. | ||||
|  | ||||
| ``` | ||||
| #include <boost/scoped_ptr.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } }; | ||||
|  | ||||
| class MyClass { | ||||
|     boost::scoped_ptr<int> ptr; | ||||
|   public: | ||||
|     MyClass() : ptr(new int) { *ptr = 0; } | ||||
|     int add_one() { return ++*ptr; } | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     boost::scoped_ptr<Shoe> x(new Shoe); | ||||
|     MyClass my_instance; | ||||
|     std::cout << my_instance.add_one() << '\n'; | ||||
|     std::cout << my_instance.add_one() << '\n'; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| The example program produces the beginning of a child's nursery rhyme: | ||||
|  | ||||
| ``` | ||||
| 1 | ||||
| 2 | ||||
| Buckle my shoe | ||||
| ``` | ||||
|  | ||||
| ## Rationale | ||||
|  | ||||
| The primary reason to use `scoped_ptr` rather than `std::auto_ptr` or `std::unique_ptr` is to let readers of your code | ||||
| know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership. | ||||
|  | ||||
| A secondary reason to use `scoped_ptr` is to prevent a later maintenance programmer from adding a function that transfers | ||||
| ownership by returning the `auto_ptr`, because the maintenance programmer saw `auto_ptr`, and assumed ownership could safely be transferred. | ||||
|  | ||||
| Think of `bool` vs `int`. We all know that under the covers `bool` is usually just an `int`. Indeed, some argued against including bool in the {cpp} | ||||
| standard because of that. But by coding `bool` rather than `int`, you tell your readers what your intent is. Same with `scoped_ptr`; by using it you are signaling intent. | ||||
|  | ||||
| It has been suggested that `scoped_ptr<T>` is equivalent to `std::auto_ptr<T> const`. Ed Brey pointed out, however, that `reset` will not work on a `std::auto_ptr<T> const`. | ||||
|  | ||||
| ## Handle/Body Idiom | ||||
|  | ||||
| One common usage of `scoped_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file. | ||||
|  | ||||
| The `link:../../example/scoped_ptr_example_test.cpp[scoped_ptr_example_test.cpp]` sample program includes a header file, | ||||
| `link:../../example/scoped_ptr_example.hpp[scoped_ptr_example.hpp]`, which uses a `scoped_ptr<>` to an incomplete type to hide the | ||||
| implementation. The instantiation of member functions which require a complete type occurs in the `link:../../example/scoped_ptr_example.cpp[scoped_ptr_example.cpp]` | ||||
| implementation file. | ||||
|  | ||||
| ## Frequently Asked Questions | ||||
|  | ||||
| [qanda] | ||||
| Why doesn't `scoped_ptr` have a `release()` member?:: | ||||
|  | ||||
|   When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If `scoped_ptr` had a `release()` member, | ||||
|   it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use `std::auto_ptr` where | ||||
|   transfer of ownership is required. (supplied by Dave Abrahams) | ||||
							
								
								
									
										300
									
								
								doc/smart_ptr/shared_array.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								doc/smart_ptr/shared_array.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| //// | ||||
| Copyright 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [[shared_array]] | ||||
| [appendix] | ||||
| # shared_array (deprecated) | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: shared_array_ | ||||
|  | ||||
| NOTE: This facility is deprecated because a `shared_ptr` to `T[]` or `T[N]` | ||||
| is now available, and is superior in every regard. | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `shared_array` class template stores a pointer to a dynamically allocated | ||||
| array. (Dynamically allocated array are allocated with the C++ `new[]` | ||||
| expression.) The object pointed to is guaranteed to be deleted when the last | ||||
| `shared_array` pointing to it is destroyed or reset. | ||||
|  | ||||
| Every `shared_array` meets the _CopyConstructible_ and _Assignable_ | ||||
| requirements of the {cpp} Standard Library, and so can be used in standard | ||||
| library containers. Comparison operators are supplied so that shared_array | ||||
| works with the standard library's associative containers. | ||||
|  | ||||
| Normally, a `shared_array` cannot correctly hold a pointer to an object that | ||||
| has been allocated with the non-array form of `new`. See `shared_ptr` for that | ||||
| usage. | ||||
|  | ||||
| Because the implementation uses reference counting, cycles of `shared_array` | ||||
| instances will not be reclaimed. For example, if `main` holds a shared_array | ||||
| to `A`, which directly or indirectly holds a shared_array back to `A`, the use | ||||
| count of `A` will be 2. Destruction of the original `shared_array` will leave | ||||
| `A` dangling with a use count of 1. | ||||
|  | ||||
| A `shared_ptr` to a `std::vector` is an alternative to a `shared_array` that | ||||
| is a bit heavier duty but far more flexible. | ||||
|  | ||||
| The class template is parameterized on `T`, the type of the object pointed to. | ||||
| `shared_array` and most of its member functions place no requirements on `T`; | ||||
| it is allowed to be an incomplete type, or `void`. Member functions that do | ||||
| place additional requirements (constructors, reset) are explicitly documented | ||||
| below. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class shared_array { | ||||
|   public: | ||||
|     typedef T element_type; | ||||
|  | ||||
|     explicit shared_array(T* p = 0); | ||||
|     template<class D> shared_array(T* p, D d); | ||||
|     shared_array(const shared_array& v) noexcept; | ||||
|  | ||||
|     ~shared_array() noexcept; | ||||
|  | ||||
|     shared_array& operator=(const shared_array& v) noexcept; | ||||
|  | ||||
|     void reset(T* p = 0); | ||||
|     template<class D> void reset(T* p, D d); | ||||
|  | ||||
|     T& operator[](std::ptrdiff_t n) const noexcept; | ||||
|     T* get() const noexcept; | ||||
|  | ||||
|     bool unique() const noexcept; | ||||
|     long use_count() const noexcept; | ||||
|  | ||||
|     explicit operator bool() const noexcept; | ||||
|  | ||||
|     void swap(shared_array<T>& v) noexcept; | ||||
|   }; | ||||
|  | ||||
|   template<class T> bool | ||||
|     operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept; | ||||
|   template<class T> bool | ||||
|     operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept; | ||||
|   template<class T> bool | ||||
|     operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept; | ||||
|  | ||||
|   template<class T> | ||||
|     void swap(shared_array<T>& a, shared_array<T>& b) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### element_type | ||||
|  | ||||
| ``` | ||||
| typedef T element_type; | ||||
| ``` | ||||
| Type:: Provides the type of the stored pointer. | ||||
|  | ||||
| ### Constructors | ||||
|  | ||||
| ``` | ||||
| explicit shared_array(T* p = 0); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `shared_array`, storing a copy of `p`, which must be a | ||||
| pointer to an array that was allocated via a C++ `new[]` expression or be 0. | ||||
| Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`). | ||||
| Requires:: `T` is a complete type. | ||||
| Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. | ||||
|  | ||||
| ``` | ||||
| template<class D> shared_array(T* p, D d); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `shared_array`, storing a copy of `p` and of `d`. | ||||
| Afterwards, the use count is 1. When the the time comes to delete the array | ||||
| pointed to by `p`, the object `d` is used in the statement `d(p)`. | ||||
| Requires:: | ||||
| * `T` is a complete type. | ||||
| * The copy constructor and destructor of `D` must not throw. | ||||
| * Invoking the object `d` with parameter `p` must not throw. | ||||
| Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. | ||||
|  | ||||
| ``` | ||||
| shared_array(const shared_array& v) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `shared_array`, as if by storing a copy of the pointer | ||||
| stored in `v`. Afterwards, the use count for all copies is 1 more than the | ||||
| initial use count. | ||||
| Requires:: `T` is a complete type. | ||||
|  | ||||
| ### Destructor | ||||
|  | ||||
| ``` | ||||
| ~shared_array() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Decrements the use count. Then, if the use count is 0, deletes the | ||||
| array pointed to by the stored pointer. Note that `delete[]` on a pointer with | ||||
| a value of 0 is harmless.  | ||||
|  | ||||
| ### Assignment | ||||
|  | ||||
| ``` | ||||
| shared_array& operator=(const shared_array& v) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a new `shared_array` as described above, then replaces | ||||
| this `shared_array` with the new one, destroying the replaced object. | ||||
| Requires:: `T` is a complete type. | ||||
| Returns:: `*this`. | ||||
|  | ||||
| ### reset | ||||
|  | ||||
| ``` | ||||
| void reset(T* p = 0); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a new `shared_array` as described above, then replaces | ||||
| this `shared_array` with the new one, destroying the replaced object. | ||||
| Requires:: `T` is a complete type. | ||||
| Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. | ||||
|  | ||||
| ``` | ||||
| template<class D> void reset(T* p, D d); | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a new `shared_array` as described above, then replaces | ||||
| this `shared_array` with the new one, destroying the replaced object. | ||||
| Requires:: | ||||
| * `T` is a complete type. | ||||
| * The copy constructor of `D` must not throw. | ||||
| Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. | ||||
|  | ||||
| ### Indexing | ||||
|  | ||||
| ``` | ||||
| T& operator[](std::ptrdiff_t n) const noexcept; | ||||
| ``` | ||||
| Returns:: A reference to element `n` of the array pointed to by the stored | ||||
| pointer. Behavior is undefined and almost certainly undesirable if the stored | ||||
| pointer is 0, or if `n` is less than 0 or is greater than or equal to the | ||||
| number of elements in the array. | ||||
| Requires:: `T` is a complete type. | ||||
|  | ||||
| ### get | ||||
|  | ||||
| ``` | ||||
| T* get() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   The stored pointer. | ||||
|  | ||||
| ### unique | ||||
|  | ||||
| ``` | ||||
| bool unique() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `true` if no other `shared_array` is sharing ownership of the stored pointer, `false` otherwise. | ||||
|  | ||||
| ### use_count | ||||
|  | ||||
| ``` | ||||
| long use_count() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: The number of `shared_array` objects sharing ownership of the | ||||
| stored pointer. | ||||
|  | ||||
| ### Conversions | ||||
|  | ||||
| ``` | ||||
| explicit operator bool() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `get() != 0`. | ||||
| Requires:: `T` is a complete type. | ||||
|  | ||||
| ### swap | ||||
|  | ||||
| ``` | ||||
| void swap(shared_array<T>& b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Exchanges the contents of the two smart pointers. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### Comparison | ||||
|  | ||||
| ``` | ||||
| template<class T> bool | ||||
|   operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T> bool | ||||
|   operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class T> bool | ||||
|   operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: The result of comparing the stored pointers of the two smart | ||||
| pointers. | ||||
|  | ||||
| NOTE: The `operator<` overload is provided to define an ordering so that | ||||
| `shared_array` objects can be used in associative containers such as | ||||
| `std::map`. The implementation uses `std::less<T*>` to perform the comparison. | ||||
| This ensures that the comparison is handled correctly, since the standard | ||||
| mandates that relational operations on pointers are unspecified (5.9 | ||||
| [expr.rel] paragraph 2) but `std::less` on pointers is well-defined (20.3.3 | ||||
| [lib.comparisons] paragraph 8). | ||||
|  | ||||
| ### swap | ||||
|  | ||||
| ``` | ||||
| template<class T> | ||||
|   void swap(shared_array<T>& a, shared_array<T>& b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `a.swap(b)`. | ||||
| Requires:: `T` is a complete type. | ||||
							
								
								
									
										1071
									
								
								doc/smart_ptr/shared_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1071
									
								
								doc/smart_ptr/shared_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										768
									
								
								doc/smart_ptr/techniques.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										768
									
								
								doc/smart_ptr/techniques.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,768 @@ | ||||
| //// | ||||
| Copyright 2003, 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [[techniques]] | ||||
| [appendix] | ||||
| # Smart Pointer Programming Techniques | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: techniques_ | ||||
|  | ||||
| [#techniques_incomplete] | ||||
| ## Using incomplete classes for implementation hiding | ||||
|  | ||||
| A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle: | ||||
|  | ||||
| ``` | ||||
| class FILE; | ||||
|  | ||||
| FILE * fopen(char const * name, char const * mode); | ||||
| void fread(FILE * f, void * data, size_t size); | ||||
| void fclose(FILE * f); | ||||
| ``` | ||||
|  | ||||
|  | ||||
| It is possible to express the above interface using `shared_ptr`, eliminating the need to manually call `fclose`: | ||||
|  | ||||
| ``` | ||||
| class FILE; | ||||
|  | ||||
| shared_ptr<FILE> fopen(char const * name, char const * mode); | ||||
| void fread(shared_ptr<FILE> f, void * data, size_t size); | ||||
| ``` | ||||
|  | ||||
| This technique relies on `shared_ptr`’s ability to execute a custom deleter, eliminating the explicit call to `fclose`, and on the fact that `shared_ptr<X>` can be copied and destroyed when `X` is incomplete. | ||||
|  | ||||
| ## The "Pimpl" idiom | ||||
|  | ||||
| A {cpp} specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. `shared_ptr` can be used to implement a "Pimpl": | ||||
|  | ||||
| ``` | ||||
| // file.hpp: | ||||
|  | ||||
| class file | ||||
| { | ||||
| private: | ||||
|  | ||||
|     class impl; | ||||
|     shared_ptr<impl> pimpl_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     file(char const * name, char const * mode); | ||||
|  | ||||
|     // compiler generated members are fine and useful | ||||
|  | ||||
|     void read(void * data, size_t size); | ||||
| }; | ||||
|  | ||||
| // file.cpp: | ||||
|  | ||||
| #include "file.hpp" | ||||
|  | ||||
| class file::impl | ||||
| { | ||||
| private: | ||||
|  | ||||
|     impl(impl const &); | ||||
|     impl & operator=(impl const &); | ||||
|  | ||||
|     // private data | ||||
|  | ||||
| public: | ||||
|  | ||||
|     impl(char const * name, char const * mode) { ... } | ||||
|     ~impl() { ... } | ||||
|     void read(void * data, size_t size) { ... } | ||||
| }; | ||||
|  | ||||
| file::file(char const * name, char const * mode): pimpl_(new impl(name, mode)) | ||||
| { | ||||
| } | ||||
|  | ||||
| void file::read(void * data, size_t size) | ||||
| { | ||||
|     pimpl_->read(data, size); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| The key thing to note here is that the compiler-generated copy constructor, assignment operator, and destructor all have a sensible meaning. As a result, `file` is `CopyConstructible` and `Assignable`, allowing its use in standard containers. | ||||
|  | ||||
| ## Using abstract classes for implementation hiding | ||||
|  | ||||
| Another widely used C++ idiom for separating inteface and implementation is to use abstract base classes and factory functions. | ||||
| The abstract classes are sometimes called "interfaces" and the pattern is known as "interface-based programming". Again, | ||||
| `shared_ptr` can be used as the return type of the factory functions: | ||||
|  | ||||
| ``` | ||||
| // X.hpp: | ||||
|  | ||||
| class X | ||||
| { | ||||
| public: | ||||
|  | ||||
|     virtual void f() = 0; | ||||
|     virtual void g() = 0; | ||||
|  | ||||
| protected: | ||||
|  | ||||
|     ~X() {} | ||||
| }; | ||||
|  | ||||
| shared_ptr<X> createX(); | ||||
|  | ||||
| // X.cpp: | ||||
|  | ||||
| class X_impl: public X | ||||
| { | ||||
| private: | ||||
|  | ||||
|     X_impl(X_impl const &); | ||||
|     X_impl & operator=(X_impl const &); | ||||
|  | ||||
| public: | ||||
|  | ||||
|     virtual void f() | ||||
|     { | ||||
|       // ... | ||||
|     } | ||||
|  | ||||
|     virtual void g() | ||||
|     { | ||||
|       // ... | ||||
|     } | ||||
| }; | ||||
|  | ||||
| shared_ptr<X> createX() | ||||
| { | ||||
|     shared_ptr<X> px(new X_impl); | ||||
|     return px; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| A key property of `shared_ptr` is that the allocation, construction, deallocation, and destruction details are captured at the point of construction, inside the factory function. | ||||
|  | ||||
| Note the protected and nonvirtual destructor in the example above. The client code cannot, and does not need to, delete a pointer to `X`; the `shared_ptr<X>` instance returned from `createX` will correctly call `~X_impl`. | ||||
|  | ||||
| ## Preventing `delete px.get()` | ||||
|  | ||||
| It is often desirable to prevent client code from deleting a pointer that is being managed by `shared_ptr`. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter: | ||||
|  | ||||
| ``` | ||||
| class X | ||||
| { | ||||
| private: | ||||
|  | ||||
|     ~X(); | ||||
|  | ||||
|     class deleter; | ||||
|     friend class deleter; | ||||
|  | ||||
|     class deleter | ||||
|     { | ||||
|     public: | ||||
|  | ||||
|         void operator()(X * p) { delete p; } | ||||
|     }; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     static shared_ptr<X> create() | ||||
|     { | ||||
|         shared_ptr<X> px(new X, X::deleter()); | ||||
|         return px; | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| ## Encapsulating allocation details, wrapping factory functions | ||||
|  | ||||
| `shared_ptr` can be used in creating {cpp} wrappers over existing C style library interfaces that return raw pointers from their factory functions | ||||
| to encapsulate allocation details. As an example, consider this interface, where `CreateX` might allocate `X` from its own private heap, `~X` may | ||||
| be inaccessible, or `X` may be incomplete: | ||||
|  | ||||
|     X * CreateX(); | ||||
|     void DestroyX(X *); | ||||
|  | ||||
| The only way to reliably destroy a pointer returned by `CreateX` is to call `DestroyX`. | ||||
|  | ||||
| Here is how a `shared_ptr`-based wrapper may look like: | ||||
|  | ||||
|     shared_ptr<X> createX() | ||||
|     { | ||||
|         shared_ptr<X> px(CreateX(), DestroyX); | ||||
|         return px; | ||||
|     } | ||||
|  | ||||
| Client code that calls `createX` still does not need to know how the object has been allocated, but now the destruction is automatic. | ||||
|  | ||||
| [#techniques_static] | ||||
| ## Using a shared_ptr to hold a pointer to a statically allocated object | ||||
|  | ||||
| Sometimes it is desirable to create a `shared_ptr` to an already existing object, so that the `shared_ptr` does not attempt to destroy the | ||||
| object when there are no more references left. As an example, the factory function: | ||||
|  | ||||
|     shared_ptr<X> createX(); | ||||
|  | ||||
| in certain situations may need to return a pointer to a statically allocated `X` instance. | ||||
|  | ||||
| The solution is to use a custom deleter that does nothing: | ||||
|  | ||||
| ``` | ||||
| struct null_deleter | ||||
| { | ||||
|     void operator()(void const *) const | ||||
|     { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| static X x; | ||||
|  | ||||
| shared_ptr<X> createX() | ||||
| { | ||||
|     shared_ptr<X> px(&x, null_deleter()); | ||||
|     return px; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| The same technique works for any object known to outlive the pointer. | ||||
|  | ||||
| ## Using a shared_ptr to hold a pointer to a COM Object | ||||
|  | ||||
| Background: COM objects have an embedded reference count and two member functions that manipulate it. `AddRef()` increments the count. | ||||
| `Release()` decrements the count and destroys itself when the count drops to zero. | ||||
|  | ||||
| It is possible to hold a pointer to a COM object in a `shared_ptr`: | ||||
|  | ||||
|     shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p) | ||||
|     { | ||||
|         p->AddRef(); | ||||
|         shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release)); | ||||
|         return pw; | ||||
|     } | ||||
|  | ||||
| Note, however, that `shared_ptr` copies created from `pw` will not "register" in the embedded count of the COM object; | ||||
| they will share the single reference created in `make_shared_from_COM`. Weak pointers created from `pw` will be invalidated when the last | ||||
| `shared_ptr` is destroyed, regardless of whether the COM object itself is still alive. | ||||
|  | ||||
| As link:../../../../libs/bind/mem_fn.html#Q3[explained] in the `mem_fn` documentation, you need to `#define BOOST_MEM_FN_ENABLE_STDCALL` first. | ||||
|  | ||||
| [#techniques_intrusive] | ||||
| ## Using a shared_ptr to hold a pointer to an object with an embedded reference count | ||||
|  | ||||
| This is a generalization of the above technique. The example assumes that the object implements the two functions required by `<<intrusive_ptr,intrusive_ptr>>`, | ||||
| `intrusive_ptr_add_ref` and `intrusive_ptr_release`: | ||||
|  | ||||
| ``` | ||||
| template<class T> struct intrusive_deleter | ||||
| { | ||||
|     void operator()(T * p) | ||||
|     { | ||||
|         if(p) intrusive_ptr_release(p); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| shared_ptr<X> make_shared_from_intrusive(X * p) | ||||
| { | ||||
|     if(p) intrusive_ptr_add_ref(p); | ||||
|     shared_ptr<X> px(p, intrusive_deleter<X>()); | ||||
|     return px; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Using a shared_ptr to hold another shared ownership smart pointer | ||||
|  | ||||
| One of the design goals of `shared_ptr` is to be used in library interfaces. It is possible to encounter a situation where a library takes a | ||||
| `shared_ptr` argument, but the object at hand is being managed by a different reference counted or linked smart pointer. | ||||
|  | ||||
| It is possible to exploit `shared_ptr`’s custom deleter feature to wrap this existing smart pointer behind a `shared_ptr` facade: | ||||
|  | ||||
| ``` | ||||
| template<class P> struct smart_pointer_deleter | ||||
| { | ||||
| private: | ||||
|  | ||||
|     P p_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     smart_pointer_deleter(P const & p): p_(p) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void operator()(void const *) | ||||
|     { | ||||
|         p_.reset(); | ||||
|     } | ||||
|      | ||||
|     P const & get() const | ||||
|     { | ||||
|         return p_; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| shared_ptr<X> make_shared_from_another(another_ptr<X> qx) | ||||
| { | ||||
|     shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx)); | ||||
|     return px; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that `p_.reset()` doesn't throw. | ||||
| If this is not the case, `p_.reset();` should be wrapped in a `try {} catch(...) {}` block that ignores exceptions. In the (usually unlikely) event | ||||
| when an exception is thrown and ignored, `p_` will be released when the lifetime of the deleter ends. This happens when all references, including | ||||
| weak pointers, are destroyed or reset. | ||||
|  | ||||
| Another twist is that it is possible, given the above `shared_ptr` instance, to recover the original smart pointer, using `<<shared_ptr_get_deleter,get_deleter>>`: | ||||
|  | ||||
| ``` | ||||
| void extract_another_from_shared(shared_ptr<X> px) | ||||
| { | ||||
|     typedef smart_pointer_deleter< another_ptr<X> > deleter; | ||||
|  | ||||
|     if(deleter const * pd = get_deleter<deleter>(px)) | ||||
|     { | ||||
|         another_ptr<X> qx = pd->get(); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // not one of ours | ||||
|     } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| [#techniques_from_raw] | ||||
| ## Obtaining a shared_ptr from a raw pointer | ||||
|  | ||||
| Sometimes it is necessary to obtain a `shared_ptr` given a raw pointer to an object that is already managed by another `shared_ptr` instance. Example: | ||||
|  | ||||
|     void f(X * p) | ||||
|     { | ||||
|         shared_ptr<X> px(???); | ||||
|     } | ||||
|  | ||||
| Inside `f`, we'd like to create a `shared_ptr` to `*p`. | ||||
|  | ||||
| In the general case, this problem has no solution. One approach is to modify `f` to take a `shared_ptr`, if possible: | ||||
|  | ||||
|     void f(shared_ptr<X> px); | ||||
|  | ||||
| The same transformation can be used for nonvirtual member functions, to convert the implicit `this`: | ||||
|  | ||||
|     void X::f(int m); | ||||
|  | ||||
| would become a free function with a `shared_ptr` first argument: | ||||
|  | ||||
|     void f(shared_ptr<X> this_, int m); | ||||
|  | ||||
| If `f` cannot be changed, but `X` uses intrusive counting, use `<<techniques_intrusive,make_shared_from_intrusive>>` described above. Or, if it's known that the `shared_ptr` created in `f` will never outlive the object, use <<techniques_static,a null deleter>>. | ||||
|  | ||||
| ## Obtaining a shared_ptr (weak_ptr) to this in a constructor | ||||
|  | ||||
| Some designs require objects to register themselves on construction with a central authority. When the registration routines take a `shared_ptr`, this leads to the question how could a constructor obtain a `shared_ptr` to `this`: | ||||
|  | ||||
| ``` | ||||
| class X | ||||
| { | ||||
| public: | ||||
|  | ||||
|     X() | ||||
|     { | ||||
|         shared_ptr<X> this_(???); | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| In the general case, the problem cannot be solved. The `X` instance being constructed can be an automatic variable or a static variable; it can be created on the heap: | ||||
|  | ||||
|     shared_ptr<X> px(new X); | ||||
|  | ||||
| but at construction time, `px` does not exist yet, and it is impossible to create another `shared_ptr` instance that shares ownership with it. | ||||
|  | ||||
| Depending on context, if the inner `shared_ptr this_` doesn't need to keep the object alive, use a `null_deleter` as explained <<techniques_static,here>> and <<techniques_weak_without_shared,here>>. | ||||
| If `X` is supposed to always live on the heap, and be managed by a `shared_ptr`, use a static factory function: | ||||
|  | ||||
| ``` | ||||
| class X | ||||
| { | ||||
| private: | ||||
|  | ||||
|     X() { ... } | ||||
|  | ||||
| public: | ||||
|  | ||||
|     static shared_ptr<X> create() | ||||
|     { | ||||
|         shared_ptr<X> px(new X); | ||||
|         // use px as 'this_' | ||||
|         return px; | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| ## Obtaining a shared_ptr to this | ||||
|  | ||||
| Sometimes it is needed to obtain a `shared_ptr` from `this` in a virtual member function under the assumption that `this` is already managed by a `shared_ptr`. | ||||
| The transformations <<techniques_from_raw,described in the previous technique>> cannot be applied. | ||||
|  | ||||
| A typical example: | ||||
|  | ||||
| ``` | ||||
| class X | ||||
| { | ||||
| public: | ||||
|  | ||||
|     virtual void f() = 0; | ||||
|  | ||||
| protected: | ||||
|  | ||||
|     ~X() {} | ||||
| }; | ||||
|  | ||||
| class Y | ||||
| { | ||||
| public: | ||||
|  | ||||
|     virtual shared_ptr<X> getX() = 0; | ||||
|  | ||||
| protected: | ||||
|  | ||||
|     ~Y() {} | ||||
| }; | ||||
|  | ||||
| // -- | ||||
|  | ||||
| class impl: public X, public Y | ||||
| { | ||||
| public: | ||||
|  | ||||
|     impl() { ... } | ||||
|  | ||||
|     virtual void f() { ... } | ||||
|  | ||||
|     virtual shared_ptr<X> getX() | ||||
|     { | ||||
|         shared_ptr<X> px(???); | ||||
|         return px; | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| The solution is to keep a weak pointer to `this` as a member in `impl`: | ||||
|  | ||||
| ``` | ||||
| class impl: public X, public Y | ||||
| { | ||||
| private: | ||||
|  | ||||
|     weak_ptr<impl> weak_this; | ||||
|  | ||||
|     impl(impl const &); | ||||
|     impl & operator=(impl const &); | ||||
|  | ||||
|     impl() { ... } | ||||
|  | ||||
| public: | ||||
|  | ||||
|     static shared_ptr<impl> create() | ||||
|     { | ||||
|         shared_ptr<impl> pi(new impl); | ||||
|         pi->weak_this = pi; | ||||
|         return pi; | ||||
|     } | ||||
|  | ||||
|     virtual void f() { ... } | ||||
|  | ||||
|     virtual shared_ptr<X> getX() | ||||
|     { | ||||
|         shared_ptr<X> px(weak_this); | ||||
|         return px; | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| The library now includes a helper class template `<<enable_shared_from_this,enable_shared_from_this>>` that can be used to encapsulate the solution: | ||||
|  | ||||
| ``` | ||||
| class impl: public X, public Y, public enable_shared_from_this<impl> | ||||
| { | ||||
| public: | ||||
|  | ||||
|     impl(impl const &); | ||||
|     impl & operator=(impl const &); | ||||
|  | ||||
| public: | ||||
|  | ||||
|     virtual void f() { ... } | ||||
|  | ||||
|     virtual shared_ptr<X> getX() | ||||
|     { | ||||
|         return shared_from_this(); | ||||
|     } | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Note that you no longer need to manually initialize the `weak_ptr` member in `enable_shared_from_this`. Constructing a `shared_ptr` to `impl` takes care of that. | ||||
|  | ||||
| ## Using shared_ptr as a smart counted handle | ||||
|  | ||||
| Some library interfaces use opaque handles, a variation of the <<techniques_incomplete,incomplete class technique>> described above. An example: | ||||
|  | ||||
| ``` | ||||
| typedef void * HANDLE; | ||||
|  | ||||
| HANDLE CreateProcess(); | ||||
| void CloseHandle(HANDLE); | ||||
| ``` | ||||
|  | ||||
| Instead of a raw pointer, it is possible to use `shared_ptr` as the handle and get reference counting and automatic resource management for free: | ||||
|  | ||||
| ``` | ||||
| typedef shared_ptr<void> handle; | ||||
|  | ||||
| handle createProcess() | ||||
| { | ||||
|     shared_ptr<void> pv(CreateProcess(), CloseHandle); | ||||
|     return pv; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Using shared_ptr to execute code on block exit | ||||
|  | ||||
| `shared_ptr<void>` can automatically execute cleanup code when control leaves a scope. | ||||
|  | ||||
| * Executing `f(p)`, where `p` is a pointer: | ||||
| + | ||||
| ``` | ||||
| shared_ptr<void> guard(p, f); | ||||
| ``` | ||||
|  | ||||
| * Executing arbitrary code: `f(x, y)`: | ||||
| + | ||||
| ``` | ||||
| shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y)); | ||||
| ``` | ||||
|  | ||||
| ## Using shared_ptr<void> to hold an arbitrary object | ||||
|  | ||||
| `shared_ptr<void>` can act as a generic object pointer similar to `void*`. When a `shared_ptr<void>` instance constructed as: | ||||
|  | ||||
|     shared_ptr<void> pv(new X); | ||||
|  | ||||
| is destroyed, it will correctly dispose of the `X` object by executing `~X`. | ||||
|  | ||||
| This propery can be used in much the same manner as a raw `void*` is used to temporarily strip type information from an object pointer. | ||||
| A `shared_ptr<void>` can later be cast back to the correct type by using `<<shared_ptr_static_pointer_cast,static_pointer_cast>>`. | ||||
|  | ||||
| ## Associating arbitrary data with heterogeneous `shared_ptr` instances | ||||
|  | ||||
| `shared_ptr` and `weak_ptr` support `operator<` comparisons required by standard associative containers such as `std::map`. This can be | ||||
| used to non-intrusively associate arbitrary data with objects managed by `shared_ptr`: | ||||
|  | ||||
| ``` | ||||
| typedef int Data; | ||||
|  | ||||
| std::map<shared_ptr<void>, Data> userData; | ||||
| // or std::map<weak_ptr<void>, Data> userData; to not affect the lifetime | ||||
|  | ||||
| shared_ptr<X> px(new X); | ||||
| shared_ptr<int> pi(new int(3)); | ||||
|  | ||||
| userData[px] = 42; | ||||
| userData[pi] = 91; | ||||
| ``` | ||||
|  | ||||
| ## Using `shared_ptr` as a `CopyConstructible` mutex lock | ||||
|  | ||||
| Sometimes it's necessary to return a mutex lock from a function, and a noncopyable lock cannot be returned by value. It is possible to use `shared_ptr` as a mutex lock: | ||||
|  | ||||
| ``` | ||||
| class mutex | ||||
| { | ||||
| public: | ||||
|  | ||||
|     void lock(); | ||||
|     void unlock(); | ||||
| }; | ||||
|  | ||||
| shared_ptr<mutex> lock(mutex & m) | ||||
| { | ||||
|     m.lock(); | ||||
|     return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock)); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Better yet, the `shared_ptr` instance acting as a lock can be encapsulated in a dedicated `shared_lock` class: | ||||
|  | ||||
| ``` | ||||
| class shared_lock | ||||
| { | ||||
| private: | ||||
|  | ||||
|     shared_ptr<void> pv; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {} | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| `shared_lock` can now be used as: | ||||
|  | ||||
|     shared_lock lock(m); | ||||
|  | ||||
| Note that `shared_lock` is not templated on the mutex type, thanks to `shared_ptr<void>`’s ability to hide type information. | ||||
|  | ||||
| ## Using shared_ptr to wrap member function calls | ||||
|  | ||||
| `shared_ptr` implements the ownership semantics required from the `Wrap/CallProxy` scheme described in Bjarne Stroustrup's article | ||||
| "Wrapping C++ Member Function Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below: | ||||
|  | ||||
| ``` | ||||
| template<class T> class pointer | ||||
| { | ||||
| private: | ||||
|  | ||||
|     T * p_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     explicit pointer(T * p): p_(p) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     shared_ptr<T> operator->() const | ||||
|     { | ||||
|         p_->prefix(); | ||||
|         return shared_ptr<T>(p_, mem_fn(&T::suffix)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class X | ||||
| { | ||||
| private: | ||||
|  | ||||
|     void prefix(); | ||||
|     void suffix(); | ||||
|     friend class pointer<X>; | ||||
|      | ||||
| public: | ||||
|  | ||||
|     void f(); | ||||
|     void g(); | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     X x; | ||||
|  | ||||
|     pointer<X> px(&x); | ||||
|  | ||||
|     px->f(); | ||||
|     px->g(); | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Delayed deallocation | ||||
|  | ||||
| In some situations, a single `px.reset()` can trigger an expensive deallocation in a performance-critical region: | ||||
|  | ||||
| ``` | ||||
| class X; // ~X is expensive | ||||
|  | ||||
| class Y | ||||
| { | ||||
|     shared_ptr<X> px; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     void f() | ||||
|     { | ||||
|         px.reset(); | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| The solution is to postpone the potential deallocation by moving `px` to a dedicated free list that can be periodically emptied when performance and response times are not an issue: | ||||
|  | ||||
| ``` | ||||
| vector< shared_ptr<void> > free_list; | ||||
|  | ||||
| class Y | ||||
| { | ||||
|     shared_ptr<X> px; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     void f() | ||||
|     { | ||||
|         free_list.push_back(px); | ||||
|         px.reset(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // periodically invoke free_list.clear() when convenient | ||||
| ``` | ||||
|  | ||||
| Another variation is to move the free list logic to the construction point by using a delayed deleter: | ||||
|  | ||||
| ``` | ||||
| struct delayed_deleter | ||||
| { | ||||
|     template<class T> void operator()(T * p) | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             shared_ptr<void> pv(p); | ||||
|             free_list.push_back(pv); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| [#techniques_weak_without_shared] | ||||
| ## Weak pointers to objects not managed by a shared_ptr | ||||
|  | ||||
| Make the object hold a `shared_ptr` to itself, using a `null_deleter`: | ||||
|  | ||||
| ``` | ||||
| class X | ||||
| { | ||||
| private: | ||||
|  | ||||
|     shared_ptr<X> this_; | ||||
|     int i_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     explicit X(int i): this_(this, null_deleter()), i_(i) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     // repeat in all constructors (including the copy constructor!) | ||||
|  | ||||
|     X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     // do not forget to not assign this_ in the copy assignment | ||||
|  | ||||
|     X & operator=(X const & rhs) | ||||
|     { | ||||
|         i_ = rhs.i_; | ||||
|     } | ||||
|  | ||||
|     weak_ptr<X> get_weak_ptr() const { return this_; } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| When the object's lifetime ends, `X::this_` will be destroyed, and all weak pointers will automatically expire. | ||||
							
								
								
									
										368
									
								
								doc/smart_ptr/weak_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								doc/smart_ptr/weak_ptr.adoc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,368 @@ | ||||
| //// | ||||
| Copyright 1999 Greg Colvin and Beman Dawes | ||||
| Copyright 2002 Darin Adler | ||||
| Copyright 2002-2005, 2017 Peter Dimov | ||||
|  | ||||
| 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 | ||||
| //// | ||||
|  | ||||
| [#weak_ptr] | ||||
| # weak_ptr: Non-owning Observer | ||||
| :toc: | ||||
| :toc-title: | ||||
| :idprefix: weak_ptr_ | ||||
|  | ||||
| ## Description | ||||
|  | ||||
| The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`. | ||||
| To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking | ||||
| `weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the | ||||
| object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted | ||||
| object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will | ||||
| return an empty `shared_ptr`. | ||||
|  | ||||
| Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so | ||||
| can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard | ||||
| library's associative containers. | ||||
|  | ||||
| `weak_ptr` operations never throw exceptions. | ||||
|  | ||||
| The class template is parameterized on `T`, the type of the object pointed to. | ||||
|  | ||||
| Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is | ||||
| often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined | ||||
| behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent | ||||
| piece of code: | ||||
|  | ||||
| ``` | ||||
| shared_ptr<int> p(new int(5)); | ||||
| weak_ptr<int> q(p); | ||||
|  | ||||
| // some time later | ||||
|  | ||||
| if(int * r = q.get()) | ||||
| { | ||||
|     // use *r | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer. | ||||
|  | ||||
| The solution to this problem is to create a temporary `shared_ptr` from `q`: | ||||
|  | ||||
| ``` | ||||
| shared_ptr<int> p(new int(5)); | ||||
| weak_ptr<int> q(p); | ||||
|  | ||||
| // some time later | ||||
|  | ||||
| if(shared_ptr<int> r = q.lock()) | ||||
| { | ||||
|     // use *r | ||||
| } | ||||
| ``` | ||||
|  | ||||
| Now `r` holds a reference to the object that was pointed by `q`. Even if `p.reset()` is executed in another thread, the object will stay alive until | ||||
| `r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction. | ||||
|  | ||||
| ## Synopsis | ||||
|  | ||||
| `weak_ptr` is defined in `<boost/smart_ptr/weak_ptr.hpp>`. | ||||
|  | ||||
| ``` | ||||
| namespace boost { | ||||
|  | ||||
|   template<class T> class weak_ptr { | ||||
|   public: | ||||
|  | ||||
|     typedef /*see below*/ element_type; | ||||
|  | ||||
|     weak_ptr() noexcept; | ||||
|  | ||||
|     template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept; | ||||
|     weak_ptr(weak_ptr const & r) noexcept; | ||||
|     template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept; | ||||
|  | ||||
|     weak_ptr(weak_ptr && r) noexcept; | ||||
|  | ||||
|     template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept; | ||||
|     template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept; | ||||
|     template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept; | ||||
|  | ||||
|     ~weak_ptr() noexcept; | ||||
|  | ||||
|     weak_ptr & operator=(weak_ptr const & r) noexcept; | ||||
|     weak_ptr & operator=(weak_ptr && r) noexcept; | ||||
|     template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept; | ||||
|     template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept; | ||||
|  | ||||
|     long use_count() const noexcept; | ||||
|     bool expired() const noexcept; | ||||
|  | ||||
|     bool empty() const noexcept; | ||||
|  | ||||
|     shared_ptr<T> lock() const noexcept; | ||||
|  | ||||
|     void reset() noexcept; | ||||
|  | ||||
|     void swap(weak_ptr<T> & b) noexcept; | ||||
|  | ||||
|     template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept; | ||||
|     template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept; | ||||
|  | ||||
|     template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept; | ||||
|     template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept; | ||||
|  | ||||
|     std::size_t owner_hash_value() const noexcept; | ||||
|   }; | ||||
|  | ||||
|   template<class T, class U> | ||||
|     bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept; | ||||
|  | ||||
|   template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| ## Members | ||||
|  | ||||
| ### element_type | ||||
| ``` | ||||
| typedef ... element_type; | ||||
| ``` | ||||
| `element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. | ||||
|  | ||||
| ### constructors | ||||
| ``` | ||||
| weak_ptr() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs an empty `weak_ptr`. | ||||
| Postconditions:: `use_count() == 0`. | ||||
|  | ||||
| ``` | ||||
| template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| weak_ptr(weak_ptr const & r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: If `r` is empty, constructs an empty `weak_ptr`; otherwise, constructs a `weak_ptr` that shares ownership with `r` as if by storing a copy of the pointer stored in `r`. | ||||
| Postconditions:: `use_count() == r.use_count()`. | ||||
|  | ||||
| ``` | ||||
| weak_ptr(weak_ptr && r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Constructs a `weak_ptr` that has the value `r` held. | ||||
| Postconditions:: `r` is empty. | ||||
|  | ||||
| ### aliasing constructors | ||||
| ``` | ||||
| template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept; | ||||
| ``` | ||||
| Effects:: Constructs a `weak_ptr` from `r` as if by using the corresponding converting/copy/move constructor, but stores `p` instead. | ||||
| Postconditions:: `use_count() == r.use_count()`. When `!expired()`, `shared_ptr<T>(*this).get() == p`. | ||||
|  | ||||
| NOTE: These constructors are an extension, not present in `std::weak_ptr`. | ||||
|  | ||||
| ### destructor | ||||
| ``` | ||||
| ~weak_ptr() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Destroys this `weak_ptr` but has no effect on the object its stored pointer points to. | ||||
|  | ||||
| ### assignment | ||||
| ``` | ||||
| weak_ptr & operator=(weak_ptr const & r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| weak_ptr & operator=(weak_ptr && r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: Equivalent to `weak_ptr(r).swap(*this)`. | ||||
|  | ||||
| NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. | ||||
|  | ||||
| ### use_count | ||||
| ``` | ||||
| long use_count() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`. | ||||
|  | ||||
| ### expired | ||||
| ``` | ||||
| bool expired() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `use_count() == 0`. | ||||
|  | ||||
| ### empty | ||||
| ``` | ||||
| bool empty() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: `true` when `*this` is empty, `false` otherwise. | ||||
|  | ||||
| NOTE: This function is an extension, not present in `std::weak_ptr`. | ||||
|  | ||||
| ### lock | ||||
| ``` | ||||
| shared_ptr<T> lock() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `expired()? shared_ptr<T>(): shared_ptr<T>(*this)`. | ||||
|  | ||||
| ### reset | ||||
| ``` | ||||
| void reset() noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Equivalent to `weak_ptr().swap(*this)`. | ||||
|  | ||||
| ### swap | ||||
| ``` | ||||
| void swap(weak_ptr & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Exchanges the contents of the two smart pointers. | ||||
|  | ||||
| ### owner_before | ||||
| ``` | ||||
| template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   See the description of `operator<`. | ||||
|  | ||||
| ### owner_equals | ||||
| ``` | ||||
| template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept; | ||||
| ``` | ||||
| ``` | ||||
| template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   `true` if and only if `*this` and `r` share ownership or are both empty. | ||||
|  | ||||
| ### owner_hash_value | ||||
| ``` | ||||
| std::size_t owner_hash_value() const noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: | ||||
|   An unspecified hash value such that two instances that share ownership | ||||
|   have the same hash value. | ||||
|  | ||||
| ## Free Functions | ||||
|  | ||||
| ### comparison | ||||
| ``` | ||||
| template<class T, class U> | ||||
|   bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Returns:: An unspecified value such that | ||||
| - `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;  | ||||
| - under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances | ||||
|   are equivalent if and only if they share ownership or are both empty. | ||||
|  | ||||
| NOTE: Allows `weak_ptr` objects to be used as keys in associative containers. | ||||
|  | ||||
| ### swap | ||||
| ``` | ||||
| template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept; | ||||
| ``` | ||||
| [none] | ||||
| * {blank} | ||||
| + | ||||
| Effects:: | ||||
|   Equivalent to `a.swap(b)`. | ||||
|  | ||||
| ## Frequently Asked Questions | ||||
|  | ||||
| [qanda] | ||||
| Can an object create a weak_ptr to itself in its constructor?:: | ||||
|  | ||||
|   No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no | ||||
|   `shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`, | ||||
|   it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire. | ||||
| + | ||||
| The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`: | ||||
| + | ||||
| ``` | ||||
| class X | ||||
| { | ||||
| private: | ||||
|  | ||||
|     X(); | ||||
|  | ||||
| public: | ||||
|  | ||||
|     static shared_ptr<X> create() | ||||
|     { | ||||
|         shared_ptr<X> px(new X); | ||||
|         // create weak pointers from px here | ||||
|         return px; | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
| @@ -1,91 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Boost: enable_shared_from_this.hpp documentation</title> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| 	</head> | ||||
| 	<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%"> | ||||
| 		<table border="0" width="100%"> | ||||
| 			<tr> | ||||
| 				<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A> | ||||
| 				</td> | ||||
| 				<td align="center"> | ||||
| 					<h1>enable_shared_from_this.hpp</h1> | ||||
| 				</td> | ||||
| 			</tr> | ||||
| 			<tr> | ||||
| 				<td colspan="2" height="64"> </td> | ||||
| 			</tr> | ||||
| 		</table> | ||||
| 		<h3><a name="Purpose">Purpose</a></h3> | ||||
| 		<p> | ||||
| 			The header <STRONG><boost/enable_shared_from_this.hpp></STRONG> defines  | ||||
| 			the class template <STRONG>enable_shared_from_this</STRONG>. It is used as a  | ||||
| 			base class that allows a <A href="shared_ptr.htm">shared_ptr</A> to the current  | ||||
| 			object to be obtained from within a member function. | ||||
| 		</p> | ||||
| 		<P><STRONG>enable_shared_from_this<T></STRONG> defines two member functions  | ||||
| 			called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr<T></STRONG> | ||||
| 			and <STRONG>shared_ptr<T const></STRONG>, depending on constness, to <STRONG>this</STRONG>.</P> | ||||
| 		<h3><a name="Example">Example</a></h3> | ||||
| 		<pre> | ||||
| class Y: public enable_shared_from_this<Y> | ||||
| { | ||||
| public: | ||||
|  | ||||
|     shared_ptr<Y> f() | ||||
|     { | ||||
|         return shared_from_this(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     shared_ptr<Y> p(new Y); | ||||
|     shared_ptr<Y> q = p->f(); | ||||
|     assert(p == q); | ||||
|     assert(!(p < q || q < p)); // p and q must share ownership | ||||
| } | ||||
| </pre> | ||||
| 		<h3><a name="Synopsis">Synopsis</a></h3> | ||||
| 		<pre> | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> class enable_shared_from_this | ||||
| { | ||||
| public: | ||||
|  | ||||
|     shared_ptr<T> shared_from_this(); | ||||
|     shared_ptr<T const> shared_from_this() const; | ||||
| } | ||||
|  | ||||
| } | ||||
| </pre> | ||||
| 		<h4>template<class T> shared_ptr<T>  | ||||
| 			enable_shared_from_this<T>::shared_from_this();</h4> | ||||
| 		<h4>template<class T> shared_ptr<T const>  | ||||
| 			enable_shared_from_this<T>::shared_from_this() const;</h4> | ||||
| 		<blockquote> | ||||
| 			<p> | ||||
| 				<b>Requires:</b> <STRONG>enable_shared_from_this<T></STRONG> must be an  | ||||
| 				accessible base class of <b>T</b>. <STRONG>*this</STRONG> must be a subobject  | ||||
| 				of an instance <STRONG>t</STRONG> of type <STRONG>T</STRONG> . There must exist  | ||||
| 				at least one <STRONG>shared_ptr</STRONG> instance <STRONG>p</STRONG> that <EM>owns</EM> | ||||
| 				<STRONG>t</STRONG>. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<b>Returns:</b> A <b>shared_ptr<T></b> instance <b>r</b> that shares  | ||||
| 				ownership with <b>p</b>. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<b>Postconditions:</b> <tt>r.get() == this</tt>. | ||||
| 			</p> | ||||
| 		</blockquote> | ||||
| 		<p> | ||||
| 			<br> | ||||
| 			<small>Copyright <20> 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version  | ||||
| 				1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or  | ||||
| 				copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p> | ||||
| 	</body> | ||||
| </html> | ||||
							
								
								
									
										73
									
								
								extras/test/shared_ptr_mt_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								extras/test/shared_ptr_mt_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| //  shared_ptr_mt_test.cpp - tests shared_ptr with multiple threads | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright (c) 2008 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
|  | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/bind.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #include <boost/smart_ptr/detail/lightweight_thread.hpp> | ||||
|  | ||||
| #include <vector> | ||||
| #include <cstdio> | ||||
| #include <ctime> | ||||
|  | ||||
| // | ||||
|  | ||||
| int const n = 1024 * 1024; | ||||
|  | ||||
| void test( boost::shared_ptr<int> const & pi ) | ||||
| { | ||||
|     std::vector< boost::shared_ptr<int> > v; | ||||
|  | ||||
|     for( int i = 0; i < n; ++i ) | ||||
|     { | ||||
|         v.push_back( pi ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| int const m = 16; // threads | ||||
|  | ||||
| #if defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
| char const * thmodel = "POSIX"; | ||||
|  | ||||
| #else | ||||
|  | ||||
| char const * thmodel = "Windows"; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     using namespace std; // printf, clock_t, clock | ||||
|  | ||||
|     printf( "Using %s threads: %d threads, %d iterations: ", thmodel, m, n ); | ||||
|  | ||||
|     boost::shared_ptr<int> pi( new int(42) ); | ||||
|  | ||||
|     clock_t t = clock(); | ||||
|  | ||||
|     boost::detail::lw_thread_t a[ m ]; | ||||
|  | ||||
|     for( int i = 0; i < m; ++i ) | ||||
|     { | ||||
|         boost::detail::lw_thread_create( a[ i ], boost::bind( test, pi ) ); | ||||
|     } | ||||
|  | ||||
|     for( int j = 0; j < m; ++j ) | ||||
|     { | ||||
|         boost::detail::lw_thread_join( a[j] ); | ||||
|     } | ||||
|  | ||||
|     t = clock() - t; | ||||
|  | ||||
|     printf( "\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC ); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,12 +1,3 @@ | ||||
| #include <boost/config.hpp> | ||||
| 
 | ||||
| #if defined(BOOST_MSVC) | ||||
| #pragma warning(disable: 4786)  // identifier truncated in debug info
 | ||||
| #pragma warning(disable: 4710)  // function not inlined
 | ||||
| #pragma warning(disable: 4711)  // function selected for automatic inline expansion
 | ||||
| #pragma warning(disable: 4514)  // unreferenced inline removed
 | ||||
| #endif | ||||
| 
 | ||||
| //
 | ||||
| //  shared_ptr_timing_test.cpp - use to evaluate the impact of thread safety
 | ||||
| //
 | ||||
							
								
								
									
										247
									
								
								extras/test/sp_atomic_mt2_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								extras/test/sp_atomic_mt2_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,247 @@ | ||||
|  | ||||
| // Copyright (c) 2008 Peter Dimov | ||||
| // | ||||
| // 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 | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/bind.hpp> | ||||
|  | ||||
| #include <boost/thread/shared_mutex.hpp> | ||||
| #include <boost/thread/locks.hpp> | ||||
|  | ||||
| #include <boost/smart_ptr/detail/lightweight_mutex.hpp> | ||||
| #include <boost/smart_ptr/detail/lightweight_thread.hpp> | ||||
|  | ||||
| #include <vector> | ||||
| #include <numeric> | ||||
| #include <cstdio> | ||||
| #include <cstdlib> | ||||
| #include <cstddef> | ||||
| #include <ctime> | ||||
|  | ||||
| // | ||||
|  | ||||
| static void next_value( unsigned & v ) | ||||
| { | ||||
|     v = v % 2? 3 * v + 1: v / 2; | ||||
| } | ||||
|  | ||||
| struct X | ||||
| { | ||||
|     std::vector<unsigned> v_; | ||||
|  | ||||
|     explicit X( std::size_t n ): v_( n ) | ||||
|     { | ||||
|         for( std::size_t i = 0; i < n; ++i ) | ||||
|         { | ||||
|             v_[ i ] = i; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     unsigned get() const | ||||
|     { | ||||
|         return std::accumulate( v_.begin(), v_.end(), 0 ); | ||||
|     } | ||||
|  | ||||
|     void set() | ||||
|     { | ||||
|         std::for_each( v_.begin(), v_.end(), next_value ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| static boost::shared_ptr<X> ps; | ||||
|  | ||||
| static boost::detail::lightweight_mutex lm; | ||||
| static boost::shared_mutex rw; | ||||
|  | ||||
| enum prim_type | ||||
| { | ||||
|     pt_mutex, | ||||
|     pt_rwlock, | ||||
|     pt_atomics | ||||
| }; | ||||
|  | ||||
| int read_access( prim_type pt ) | ||||
| { | ||||
|     switch( pt ) | ||||
|     { | ||||
|     case pt_mutex: | ||||
|         { | ||||
|             boost::detail::lightweight_mutex::scoped_lock lock( lm ); | ||||
|             return ps->get(); | ||||
|         } | ||||
|  | ||||
|     case pt_rwlock: | ||||
|         { | ||||
|             boost::shared_lock<boost::shared_mutex> lock( rw ); | ||||
|             return ps->get(); | ||||
|         } | ||||
|  | ||||
|     case pt_atomics: | ||||
|         { | ||||
|             boost::shared_ptr<X> p2 = boost::atomic_load( &ps ); | ||||
|             return p2->get(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void write_access( prim_type pt ) | ||||
| { | ||||
|     switch( pt ) | ||||
|     { | ||||
|     case pt_mutex: | ||||
|         { | ||||
|             boost::detail::lightweight_mutex::scoped_lock lock( lm ); | ||||
|             ps->set(); | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|     case pt_rwlock: | ||||
|         { | ||||
|             boost::unique_lock<boost::shared_mutex> lock( rw ); | ||||
|             ps->set(); | ||||
|         } | ||||
|         break; | ||||
|  | ||||
|     case pt_atomics: | ||||
|         { | ||||
|             boost::shared_ptr<X> p1 = boost::atomic_load( &ps ); | ||||
|  | ||||
|             for( ;; ) | ||||
|             { | ||||
|                 boost::shared_ptr<X> p2( new X( *p1 ) ); | ||||
|                 p2->set(); | ||||
|  | ||||
|                 if( boost::atomic_compare_exchange( &ps, &p1, p2 ) ) break; | ||||
|             } | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void worker( int k, prim_type pt, int n, int r ) | ||||
| { | ||||
|     ++r; | ||||
|  | ||||
|     unsigned s = 0, nr = 0, nw = 0; | ||||
|  | ||||
|     for( int i = 0; i < n; ++i ) | ||||
|     { | ||||
|         if( i % r ) | ||||
|         { | ||||
|             s += read_access( pt ); | ||||
|             ++nr; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             write_access( pt ); | ||||
|             ++s; | ||||
|             ++nw; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     printf( "Worker %2d: %u:%u, %10u\n", k, nr, nw, s ); | ||||
| } | ||||
|  | ||||
| #if defined( BOOST_HAS_PTHREADS ) | ||||
|   char const * thmodel = "POSIX"; | ||||
| #else | ||||
|   char const * thmodel = "Windows"; | ||||
| #endif | ||||
|  | ||||
| char const * pt_to_string( prim_type pt ) | ||||
| { | ||||
|     switch( pt ) | ||||
|     { | ||||
|     case pt_mutex: | ||||
|  | ||||
|         return "mutex"; | ||||
|  | ||||
|     case pt_rwlock: | ||||
|  | ||||
|         return "rwlock"; | ||||
|  | ||||
|     case pt_atomics: | ||||
|  | ||||
|         return "atomics"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void handle_pt_option( std::string const & opt, prim_type & pt, prim_type pt2 ) | ||||
| { | ||||
|     if( opt == pt_to_string( pt2 ) ) | ||||
|     { | ||||
|         pt = pt2; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void handle_int_option( std::string const & opt, std::string const & prefix, int & k, int kmin, int kmax ) | ||||
| { | ||||
|     if( opt.substr( 0, prefix.size() ) == prefix ) | ||||
|     { | ||||
|         int v = atoi( opt.substr( prefix.size() ).c_str() ); | ||||
|  | ||||
|         if( v >= kmin && v <= kmax ) | ||||
|         { | ||||
|             k = v; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| int main( int ac, char const * av[] ) | ||||
| { | ||||
|     using namespace std; // printf, clock_t, clock | ||||
|  | ||||
|     int m = 4;          // threads | ||||
|     int n = 10000;      // vector size | ||||
|     int k = 1000000;    // iterations | ||||
|     int r = 100;        // read/write ratio, r:1 | ||||
|  | ||||
|     prim_type pt = pt_atomics; | ||||
|  | ||||
|     for( int i = 1; i < ac; ++i ) | ||||
|     { | ||||
|         handle_pt_option( av[i], pt, pt_mutex ); | ||||
|         handle_pt_option( av[i], pt, pt_rwlock ); | ||||
|         handle_pt_option( av[i], pt, pt_atomics ); | ||||
|  | ||||
|         handle_int_option( av[i], "n=", n, 1, INT_MAX ); | ||||
|         handle_int_option( av[i], "size=", n, 1, INT_MAX ); | ||||
|  | ||||
|         handle_int_option( av[i], "k=", k, 1, INT_MAX ); | ||||
|         handle_int_option( av[i], "iterations=", k, 1, INT_MAX ); | ||||
|  | ||||
|         handle_int_option( av[i], "m=", m, 1, INT_MAX ); | ||||
|         handle_int_option( av[i], "threads=", m, 1, INT_MAX ); | ||||
|  | ||||
|         handle_int_option( av[i], "r=", r, 1, INT_MAX ); | ||||
|         handle_int_option( av[i], "ratio=", r, 1, INT_MAX ); | ||||
|     } | ||||
|  | ||||
|     printf( "%s: threads=%d size=%d iterations=%d ratio=%d %s\n\n", thmodel, m, n, k, r, pt_to_string( pt ) ); | ||||
|  | ||||
|     ps.reset( new X( n ) ); | ||||
|  | ||||
|     clock_t t = clock(); | ||||
|  | ||||
|     std::vector<boost::detail::lw_thread_t> a( m ); | ||||
|  | ||||
|     for( int i = 0; i < m; ++i ) | ||||
|     { | ||||
|         boost::detail::lw_thread_create( a[ i ], boost::bind( worker, i, pt, k, r ) ); | ||||
|     } | ||||
|  | ||||
|     for( int j = 0; j < m; ++j ) | ||||
|     { | ||||
|         boost::detail::lw_thread_join( a[ j ] ); | ||||
|     } | ||||
|  | ||||
|     t = clock() - t; | ||||
|  | ||||
|     double ts = static_cast<double>( t ) / CLOCKS_PER_SEC; | ||||
|     printf( "%.3f seconds, %.3f accesses per microsecond.\n", ts, m * k / ts / 1e+6 ); | ||||
| } | ||||
							
								
								
									
										191
									
								
								extras/test/sp_atomic_mt_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								extras/test/sp_atomic_mt_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
|  | ||||
| // Copyright (c) 2008 Peter Dimov | ||||
| // | ||||
| // 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 | ||||
|  | ||||
| //#define USE_MUTEX | ||||
| //#define USE_RWLOCK | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/bind.hpp> | ||||
|  | ||||
| #if defined( USE_RWLOCK ) | ||||
| #include <boost/thread/shared_mutex.hpp> | ||||
| #include <boost/thread/locks.hpp> | ||||
| #endif | ||||
|  | ||||
| #include <boost/smart_ptr/detail/lightweight_mutex.hpp> | ||||
| #include <boost/smart_ptr/detail/lightweight_thread.hpp> | ||||
| #include <boost/core/lightweight_test.hpp> | ||||
|  | ||||
| #include <cstdio> | ||||
| #include <ctime> | ||||
|  | ||||
| // | ||||
|  | ||||
| int const n = 1024 * 1024; | ||||
|  | ||||
| struct X | ||||
| { | ||||
|     int v_; // version | ||||
|  | ||||
|     unsigned a_; | ||||
|     unsigned b_; | ||||
|  | ||||
|     X(): v_( 0 ), a_( 1 ), b_( 1 ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     int get() const | ||||
|     { | ||||
|         return a_ * 7 + b_ * 11; | ||||
|     } | ||||
|  | ||||
|     void set() | ||||
|     { | ||||
|         int tmp = get(); | ||||
|  | ||||
|         b_ = a_; | ||||
|         a_ = tmp; | ||||
|  | ||||
|         ++v_; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| static boost::shared_ptr<X> ps( new X ); | ||||
|  | ||||
| static boost::detail::lightweight_mutex lm; | ||||
|  | ||||
| #if defined( USE_RWLOCK ) | ||||
| static boost::shared_mutex rw; | ||||
| #endif | ||||
|  | ||||
| static int tr = 0; | ||||
|  | ||||
| void reader( int r ) | ||||
| { | ||||
|     int k = 0; | ||||
|     unsigned s = 0; | ||||
|  | ||||
|     for( int i = 0; i < n; ++k ) | ||||
|     { | ||||
| #if defined( USE_MUTEX ) | ||||
|  | ||||
|         boost::detail::lightweight_mutex::scoped_lock lock( lm ); | ||||
|  | ||||
|         s += ps->get(); | ||||
|  | ||||
|         BOOST_TEST( ps->v_ >= i ); | ||||
|         i = ps->v_; | ||||
|  | ||||
| #elif defined( USE_RWLOCK ) | ||||
|  | ||||
|         boost::shared_lock<boost::shared_mutex> lock( rw ); | ||||
|  | ||||
|         s += ps->get(); | ||||
|  | ||||
|         BOOST_TEST( ps->v_ >= i ); | ||||
|         i = ps->v_; | ||||
|  | ||||
| #else | ||||
|  | ||||
|         boost::shared_ptr<X> p2 = boost::atomic_load( &ps ); | ||||
|  | ||||
|         s += p2->get(); | ||||
|  | ||||
|         BOOST_TEST( p2->v_ >= i ); | ||||
|         i = p2->v_; | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     printf( "Reader %d: %9d iterations (%6.3fx), %u\n", r, k, (double)k / n, s ); | ||||
|  | ||||
|     boost::detail::lightweight_mutex::scoped_lock lock( lm ); | ||||
|     tr += k; | ||||
| } | ||||
|  | ||||
| void writer() | ||||
| { | ||||
|     for( int i = 0; i < n; ++i ) | ||||
|     { | ||||
| #if defined( USE_MUTEX ) | ||||
|  | ||||
|         boost::detail::lightweight_mutex::scoped_lock lock( lm ); | ||||
|  | ||||
|         BOOST_TEST( ps->v_ == i ); | ||||
|         ps->set(); | ||||
|  | ||||
| #elif defined( USE_RWLOCK ) | ||||
|  | ||||
|         boost::unique_lock<boost::shared_mutex> lock( rw ); | ||||
|  | ||||
|         BOOST_TEST( ps->v_ == i ); | ||||
|         ps->set(); | ||||
|  | ||||
| #else | ||||
|  | ||||
|         boost::shared_ptr<X> p2( new X( *ps ) ); | ||||
|  | ||||
|         BOOST_TEST( p2->v_ == i ); | ||||
|         p2->set(); | ||||
|  | ||||
|         boost::atomic_store( &ps, p2 ); | ||||
|  | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| #if defined( BOOST_HAS_PTHREADS ) | ||||
|   char const * thmodel = "POSIX"; | ||||
| #else | ||||
|   char const * thmodel = "Windows"; | ||||
| #endif | ||||
|  | ||||
| int const mr = 8; // reader threads | ||||
| int const mw = 1; // writer thread | ||||
|  | ||||
| #if defined( USE_MUTEX ) | ||||
|   char const * prim = "mutex"; | ||||
| #elif defined( USE_RWLOCK ) | ||||
|   char const * prim = "rwlock"; | ||||
| #else | ||||
|   char const * prim = "atomics"; | ||||
| #endif | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     using namespace std; // printf, clock_t, clock | ||||
|  | ||||
|     printf( "Using %s threads: %dR + %dW threads, %d iterations, %s\n\n", thmodel, mr, mw, n, prim ); | ||||
|  | ||||
|     clock_t t = clock(); | ||||
|  | ||||
|     boost::detail::lw_thread_t a[ mr+mw ]; | ||||
|  | ||||
|     for( int i = 0; i < mr; ++i ) | ||||
|     { | ||||
|         boost::detail::lw_thread_create( a[ i ], boost::bind( reader, i ) ); | ||||
|     } | ||||
|  | ||||
|     for( int i = mr; i < mr+mw; ++i ) | ||||
|     { | ||||
|         boost::detail::lw_thread_create( a[ i ], writer ); | ||||
|     } | ||||
|  | ||||
|     for( int j = 0; j < mr+mw; ++j ) | ||||
|     { | ||||
|         boost::detail::lw_thread_join( a[ j ] ); | ||||
|     } | ||||
|  | ||||
|     t = clock() - t; | ||||
|  | ||||
|     double ts = static_cast<double>( t ) / CLOCKS_PER_SEC; | ||||
|     printf( "%.3f seconds, %.3f reads per microsecond.\n", ts, tr / ts / 1e+6 ); | ||||
|  | ||||
|     return boost::report_errors(); | ||||
| } | ||||
							
								
								
									
										113
									
								
								extras/test/weak_ptr_mt_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								extras/test/weak_ptr_mt_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,113 @@ | ||||
| //  weak_ptr_mt_test.cpp | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright 2005, 2008 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
|  | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/weak_ptr.hpp> | ||||
| #include <boost/bind.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #include <boost/smart_ptr/detail/lightweight_thread.hpp> | ||||
|  | ||||
| #include <vector> | ||||
| #include <cstdio> | ||||
| #include <ctime> | ||||
| #include <cstdlib> | ||||
|  | ||||
| // | ||||
|  | ||||
| int const n = 16384; | ||||
| int const k = 512; // vector size | ||||
| int const m = 16; // threads | ||||
|  | ||||
| void test( std::vector< boost::shared_ptr<int> > & v ) | ||||
| { | ||||
|     using namespace std; // printf, rand | ||||
|  | ||||
|     std::vector< boost::weak_ptr<int> > w( v.begin(), v.end() ); | ||||
|  | ||||
|     int s = 0, f = 0, r = 0; | ||||
|  | ||||
|     for( int i = 0; i < n; ++i ) | ||||
|     { | ||||
|         // randomly kill a pointer | ||||
|  | ||||
|         v[ rand() % k ].reset(); | ||||
|         ++s; | ||||
|  | ||||
|         for( int j = 0; j < k; ++j ) | ||||
|         { | ||||
|             if( boost::shared_ptr<int> px = w[ j ].lock() ) | ||||
|             { | ||||
|                 ++s; | ||||
|  | ||||
|                 if( rand() & 4 ) | ||||
|                 { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // rebind anyway with prob. 50% for add_ref_lock() against weak_release() contention | ||||
|                 ++f; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 ++r; | ||||
|             } | ||||
|  | ||||
|             w[ j ] = v[ rand() % k ]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     printf( "\n%d locks, %d forced rebinds, %d normal rebinds.", s, f, r ); | ||||
| } | ||||
|  | ||||
| #if defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
| char const * thmodel = "POSIX"; | ||||
|  | ||||
| #else | ||||
|  | ||||
| char const * thmodel = "Windows"; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     using namespace std; // printf, clock_t, clock | ||||
|  | ||||
|     printf("Using %s threads: %d threads, %d * %d iterations: ", thmodel, m, n, k ); | ||||
|  | ||||
|     std::vector< boost::shared_ptr<int> > v( k ); | ||||
|  | ||||
|     for( int i = 0; i < k; ++i ) | ||||
|     { | ||||
|         v[ i ].reset( new int( 0 ) ); | ||||
|     } | ||||
|  | ||||
|     clock_t t = clock(); | ||||
|  | ||||
|     boost::detail::lw_thread_t a[ m ]; | ||||
|  | ||||
|     for( int i = 0; i < m; ++i ) | ||||
|     { | ||||
|         boost::detail::lw_thread_create( a[ i ], boost::bind( test, v ) ); | ||||
|     } | ||||
|  | ||||
|     v.resize( 0 ); // kill original copies | ||||
|  | ||||
|     for( int j = 0; j < m; ++j ) | ||||
|     { | ||||
|         boost::detail::lw_thread_join( a[j] ); | ||||
|     } | ||||
|  | ||||
|     t = clock() - t; | ||||
|  | ||||
|     printf("\n\n%.3f seconds.\n", static_cast<double>(t) / CLOCKS_PER_SEC); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,12 +1,3 @@ | ||||
| #include <boost/config.hpp> | ||||
| 
 | ||||
| #if defined(BOOST_MSVC) | ||||
| #pragma warning(disable: 4786)  // identifier truncated in debug info
 | ||||
| #pragma warning(disable: 4710)  // function not inlined
 | ||||
| #pragma warning(disable: 4711)  // function selected for automatic inline expansion
 | ||||
| #pragma warning(disable: 4514)  // unreferenced inline removed
 | ||||
| #endif | ||||
| 
 | ||||
| //
 | ||||
| //  weak_ptr_timing_test.cpp
 | ||||
| //
 | ||||
| @@ -20,6 +11,7 @@ | ||||
| 
 | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/weak_ptr.hpp> | ||||
| #include <boost/config.hpp> | ||||
| 
 | ||||
| #include <vector> | ||||
| #include <cstdio> | ||||
							
								
								
									
										
											BIN
										
									
								
								gccspeed.gif
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gccspeed.gif
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 6.4 KiB | 
| @@ -1,108 +1,14 @@ | ||||
| #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
| // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
| #include <boost/config/header_deprecated.hpp> | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count.hpp - thread/SMP safe reference counter | ||||
| // | ||||
| //  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // 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) | ||||
| // | ||||
| //  typedef <implementation-defined> boost::detail::atomic_count; | ||||
| // | ||||
| //  atomic_count a(n); | ||||
| // | ||||
| //    (n is convertible to long) | ||||
| // | ||||
| //    Effects: Constructs an atomic_count with an initial value of n | ||||
| // | ||||
| //  a; | ||||
| // | ||||
| //    Returns: (long) the current value of a | ||||
| // | ||||
| //  ++a; | ||||
| // | ||||
| //    Effects: Atomically increments the value of a | ||||
| //    Returns: nothing | ||||
| // | ||||
| //  --a; | ||||
| // | ||||
| //    Effects: Atomically decrements the value of a | ||||
| //    Returns: (long) zero if the new value of a is zero, | ||||
| //      unspecified non-zero value otherwise (usually the new value) | ||||
| // | ||||
| //    Important note: when --a returns zero, it must act as a | ||||
| //      read memory barrier (RMB); i.e. the calling thread must | ||||
| //      have a synchronized view of the memory | ||||
| // | ||||
| //    On Intel IA-32 (x86) memory is always synchronized, so this | ||||
| //      is not a problem. | ||||
| // | ||||
| //    On many architectures the atomic instructions already act as | ||||
| //      a memory barrier. | ||||
| // | ||||
| //    This property is necessary for proper reference counting, since | ||||
| //      a thread can update the contents of a shared object, then | ||||
| //      release its reference, and another thread may immediately | ||||
| //      release the last reference causing object destruction. | ||||
| // | ||||
| //    The destructor needs to have a synchronized view of the | ||||
| //      object to perform proper cleanup. | ||||
| // | ||||
| //    Original example by Alexander Terekhov: | ||||
| // | ||||
| //    Given: | ||||
| // | ||||
| //    - a mutable shared object OBJ; | ||||
| //    - two threads THREAD1 and THREAD2 each holding  | ||||
| //      a private smart_ptr object pointing to that OBJ. | ||||
| // | ||||
| //    t1: THREAD1 updates OBJ (thread-safe via some synchronization) | ||||
| //      and a few cycles later (after "unlock") destroys smart_ptr; | ||||
| // | ||||
| //    t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization  | ||||
| //      with respect to shared mutable object OBJ; OBJ destructors | ||||
| //      are called driven by smart_ptr interface... | ||||
| // | ||||
| BOOST_HEADER_DEPRECATED("<boost/smart_ptr/detail/atomic_count.hpp>") | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #ifndef BOOST_HAS_THREADS | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| typedef long atomic_count; | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| #elif defined(BOOST_AC_USE_PTHREADS) | ||||
| #  include <boost/detail/atomic_count_pthreads.hpp> | ||||
| #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) | ||||
| #  include <boost/detail/atomic_count_win32.hpp> | ||||
| #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) | ||||
| #  include <boost/detail/atomic_count_gcc.hpp> | ||||
| #elif defined(BOOST_HAS_PTHREADS) | ||||
| #  define BOOST_AC_USE_PTHREADS | ||||
| #  include <boost/detail/atomic_count_pthreads.hpp> | ||||
| #else | ||||
|  | ||||
| // Use #define BOOST_DISABLE_THREADS to avoid the error | ||||
| #error Unrecognized threading platform | ||||
|  | ||||
| #endif | ||||
| #include <boost/smart_ptr/detail/atomic_count.hpp> | ||||
|  | ||||
| #endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED | ||||
|   | ||||
| @@ -1,59 +0,0 @@ | ||||
| #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED | ||||
| #define BOOST_BAD_WEAK_PTR_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/bad_weak_ptr.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <exception> | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| # pragma warn -8026     // Functions with excep. spec. are not expanded inline | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // The standard library that comes with Borland C++ 5.5.1, 5.6.4 | ||||
| // defines std::exception and its members as having C calling | ||||
| // convention (-pc). When the definition of bad_weak_ptr | ||||
| // is compiled with -ps, the compiler issues an error. | ||||
| // Hence, the temporary #pragma option -pc below. | ||||
|  | ||||
| #if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 | ||||
| # pragma option push -pc | ||||
| #endif | ||||
|  | ||||
| class bad_weak_ptr: public std::exception | ||||
| { | ||||
| public: | ||||
|  | ||||
|     virtual char const * what() const throw() | ||||
|     { | ||||
|         return "tr1::bad_weak_ptr"; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 | ||||
| # pragma option pop | ||||
| #endif | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| # pragma warn .8026     // Functions with excep. spec. are not expanded inline | ||||
| #endif | ||||
|  | ||||
| #endif  // #ifndef BOOST_BAD_WEAK_PTR_HPP_INCLUDED | ||||
| @@ -1,42 +1,14 @@ | ||||
| #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
| // Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
| #include <boost/config/header_deprecated.hpp> | ||||
|  | ||||
| // | ||||
| //  boost/detail/lightweight_mutex.hpp - lightweight mutex | ||||
| // | ||||
| //  Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // 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) | ||||
| // | ||||
| //  typedef <unspecified> boost::detail::lightweight_mutex; | ||||
| // | ||||
| //  boost::detail::lightweight_mutex is a header-only implementation of | ||||
| //  a subset of the Mutex concept requirements: | ||||
| // | ||||
| //  http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex | ||||
| // | ||||
| //  It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. | ||||
| // | ||||
| BOOST_HEADER_DEPRECATED("<boost/smart_ptr/detail/lightweight_mutex.hpp>") | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if !defined(BOOST_HAS_THREADS) | ||||
| # include <boost/detail/lwm_nop.hpp> | ||||
| #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) | ||||
| #  include <boost/detail/lwm_win32_cs.hpp> | ||||
| #elif defined(BOOST_HAS_PTHREADS) | ||||
| #  include <boost/detail/lwm_pthreads.hpp> | ||||
| #else | ||||
| // Use #define BOOST_DISABLE_THREADS to avoid the error | ||||
| #  error Unrecognized threading platform | ||||
| #endif | ||||
| #include <boost/smart_ptr/detail/lightweight_mutex.hpp> | ||||
|  | ||||
| #endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED | ||||
|   | ||||
							
								
								
									
										15
									
								
								include/boost/detail/lightweight_thread.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/boost/detail/lightweight_thread.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| #ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED | ||||
|  | ||||
| // Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| // Copyright (c) 2008, 2018 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #include <boost/config/header_deprecated.hpp> | ||||
|  | ||||
| BOOST_HEADER_DEPRECATED("<boost/smart_ptr/detail/lightweight_thread.hpp>") | ||||
|  | ||||
| #include <boost/smart_ptr/detail/lightweight_thread.hpp> | ||||
|  | ||||
| #endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED | ||||
| @@ -1,37 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_LWM_NOP_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  boost/detail/lwm_nop.hpp | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class lightweight_mutex | ||||
| { | ||||
| public: | ||||
|  | ||||
|     typedef lightweight_mutex scoped_lock; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_DETAIL_LWM_NOP_HPP_INCLUDED | ||||
							
								
								
									
										15
									
								
								include/boost/detail/quick_allocator.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/boost/detail/quick_allocator.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
|  | ||||
| // Copyright (c) 2003 David Abrahams | ||||
| // Copyright (c) 2003 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #include <boost/config/header_deprecated.hpp> | ||||
|  | ||||
| BOOST_HEADER_DEPRECATED("<boost/smart_ptr/detail/quick_allocator.hpp>") | ||||
|  | ||||
| #include <boost/smart_ptr/detail/quick_allocator.hpp> | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
| @@ -1,151 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  detail/shared_array_nmt.hpp - shared_array.hpp without member templates | ||||
| // | ||||
| //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. | ||||
| //  Copyright (c) 2001, 2002 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/throw_exception.hpp> | ||||
| #include <boost/detail/atomic_count.hpp> | ||||
|  | ||||
| #include <cstddef>          // for std::ptrdiff_t | ||||
| #include <algorithm>        // for std::swap | ||||
| #include <functional>       // for std::less | ||||
| #include <new>              // for std::bad_alloc | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> class shared_array | ||||
| { | ||||
| private: | ||||
|  | ||||
|     typedef detail::atomic_count count_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|        | ||||
|     explicit shared_array(T * p = 0): px(p) | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try  // prevent leak if new throws | ||||
|         { | ||||
|             pn = new count_type(1); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             boost::checked_array_delete(p); | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pn = new count_type(1); | ||||
|  | ||||
|         if(pn == 0) | ||||
|         { | ||||
|             boost::checked_array_delete(p); | ||||
|             boost::throw_exception(std::bad_alloc()); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     ~shared_array() | ||||
|     { | ||||
|         if(--*pn == 0) | ||||
|         { | ||||
|             boost::checked_array_delete(px); | ||||
|             delete pn; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     shared_array(shared_array const & r) : px(r.px)  // never throws | ||||
|     { | ||||
|         pn = r.pn; | ||||
|         ++*pn; | ||||
|     } | ||||
|  | ||||
|     shared_array & operator=(shared_array const & r) | ||||
|     { | ||||
|         shared_array(r).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     void reset(T * p = 0) | ||||
|     { | ||||
|         BOOST_ASSERT(p == 0 || p != px); | ||||
|         shared_array(p).swap(*this); | ||||
|     } | ||||
|  | ||||
|     T * get() const  // never throws | ||||
|     { | ||||
|         return px; | ||||
|     } | ||||
|  | ||||
|     T & operator[](std::ptrdiff_t i) const  // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(px != 0); | ||||
|         BOOST_ASSERT(i >= 0); | ||||
|         return px[i]; | ||||
|     } | ||||
|  | ||||
|     long use_count() const  // never throws | ||||
|     { | ||||
|         return *pn; | ||||
|     } | ||||
|  | ||||
|     bool unique() const  // never throws | ||||
|     { | ||||
|         return *pn == 1; | ||||
|     } | ||||
|  | ||||
|     void swap(shared_array<T> & other)  // never throws | ||||
|     { | ||||
|         std::swap(px, other.px); | ||||
|         std::swap(pn, other.pn); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     T * px;            // contained pointer | ||||
|     count_type * pn;   // ptr to reference counter | ||||
|        | ||||
| };  // shared_array | ||||
|  | ||||
| template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b) | ||||
| { | ||||
|     return a.get() == b.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b) | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) | ||||
| { | ||||
|     return std::less<T*>()(a.get(), b.get()); | ||||
| } | ||||
|  | ||||
| template<class T> void swap(shared_array<T> & a, shared_array<T> & b) | ||||
| { | ||||
|     a.swap(b); | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED | ||||
| @@ -1,376 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/shared_count.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright 2004-2005 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| # pragma warn -8027     // Functions containing try are not expanded inline | ||||
| #endif | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/throw_exception.hpp> | ||||
| #include <boost/detail/bad_weak_ptr.hpp> | ||||
| #include <boost/detail/sp_counted_base.hpp> | ||||
| #include <boost/detail/sp_counted_impl.hpp> | ||||
|  | ||||
| #include <memory>           // std::auto_ptr | ||||
| #include <functional>       // std::less | ||||
| #include <new>              // std::bad_alloc | ||||
| #include <typeinfo>         // std::type_info in get_deleter | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| int const shared_count_id = 0x2C35F101; | ||||
| int const   weak_count_id = 0x298C38A4; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| class weak_count; | ||||
|  | ||||
| class shared_count | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base * pi_; | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|     int id_; | ||||
| #endif | ||||
|  | ||||
|     friend class weak_count; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     shared_count(): pi_(0) // nothrow | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> explicit shared_count( Y * p ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = new sp_counted_impl_p<Y>( p ); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             boost::checked_delete( p ); | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = new sp_counted_impl_p<Y>( p ); | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             boost::checked_delete( p ); | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     template<class P, class D> shared_count(P p, D d): pi_(0) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = new sp_counted_impl_pd<P, D>(p, d); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             d(p); // delete p | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = new sp_counted_impl_pd<P, D>(p, d); | ||||
|  | ||||
|         if(pi_ == 0) | ||||
|         { | ||||
|             d(p); // delete p | ||||
|             boost::throw_exception(std::bad_alloc()); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         typedef sp_counted_impl_pda<P, D, A> impl_type; | ||||
|         typedef typename A::template rebind< impl_type >::other A2; | ||||
|  | ||||
|         A2 a2( a ); | ||||
|  | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); | ||||
|             new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             d( p ); | ||||
|  | ||||
|             if( pi_ != 0 ) | ||||
|             { | ||||
|                 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); | ||||
|             } | ||||
|  | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); | ||||
|  | ||||
|         if( pi_ != 0 ) | ||||
|         { | ||||
|             new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             d( p ); | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     // auto_ptr<Y> is special cased to provide the strong guarantee | ||||
|  | ||||
|     template<class Y> | ||||
|     explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             boost::throw_exception(std::bad_alloc()); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|         r.release(); | ||||
|     } | ||||
|  | ||||
| #endif  | ||||
|  | ||||
|     ~shared_count() // nothrow | ||||
|     { | ||||
|         if( pi_ != 0 ) pi_->release(); | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         id_ = 0; | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     shared_count(shared_count const & r): pi_(r.pi_) // nothrow | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         if( pi_ != 0 ) pi_->add_ref_copy(); | ||||
|     } | ||||
|  | ||||
|     explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 | ||||
|  | ||||
|     shared_count & operator= (shared_count const & r) // nothrow | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|  | ||||
|         if( tmp != pi_ ) | ||||
|         { | ||||
|             if( tmp != 0 ) tmp->add_ref_copy(); | ||||
|             if( pi_ != 0 ) pi_->release(); | ||||
|             pi_ = tmp; | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     void swap(shared_count & r) // nothrow | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|         r.pi_ = pi_; | ||||
|         pi_ = tmp; | ||||
|     } | ||||
|  | ||||
|     long use_count() const // nothrow | ||||
|     { | ||||
|         return pi_ != 0? pi_->use_count(): 0; | ||||
|     } | ||||
|  | ||||
|     bool unique() const // nothrow | ||||
|     { | ||||
|         return use_count() == 1; | ||||
|     } | ||||
|  | ||||
|     friend inline bool operator==(shared_count const & a, shared_count const & b) | ||||
|     { | ||||
|         return a.pi_ == b.pi_; | ||||
|     } | ||||
|  | ||||
|     friend inline bool operator<(shared_count const & a, shared_count const & b) | ||||
|     { | ||||
|         return std::less<sp_counted_base *>()( a.pi_, b.pi_ ); | ||||
|     } | ||||
|  | ||||
|     void * get_deleter(std::type_info const & ti) const | ||||
|     { | ||||
|         return pi_? pi_->get_deleter( ti ): 0; | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class weak_count | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base * pi_; | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|     int id_; | ||||
| #endif | ||||
|  | ||||
|     friend class shared_count; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     weak_count(): pi_(0) // nothrow | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(weak_count_id) | ||||
| #endif | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     weak_count(shared_count const & r): pi_(r.pi_) // nothrow | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_add_ref(); | ||||
|     } | ||||
|  | ||||
|     weak_count(weak_count const & r): pi_(r.pi_) // nothrow | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_add_ref(); | ||||
|     } | ||||
|  | ||||
|     ~weak_count() // nothrow | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_release(); | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         id_ = 0; | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     weak_count & operator= (shared_count const & r) // nothrow | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|         if(tmp != 0) tmp->weak_add_ref(); | ||||
|         if(pi_ != 0) pi_->weak_release(); | ||||
|         pi_ = tmp; | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     weak_count & operator= (weak_count const & r) // nothrow | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|         if(tmp != 0) tmp->weak_add_ref(); | ||||
|         if(pi_ != 0) pi_->weak_release(); | ||||
|         pi_ = tmp; | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     void swap(weak_count & r) // nothrow | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|         r.pi_ = pi_; | ||||
|         pi_ = tmp; | ||||
|     } | ||||
|  | ||||
|     long use_count() const // nothrow | ||||
|     { | ||||
|         return pi_ != 0? pi_->use_count(): 0; | ||||
|     } | ||||
|  | ||||
|     friend inline bool operator==(weak_count const & a, weak_count const & b) | ||||
|     { | ||||
|         return a.pi_ == b.pi_; | ||||
|     } | ||||
|  | ||||
|     friend inline bool operator<(weak_count const & a, weak_count const & b) | ||||
|     { | ||||
|         return std::less<sp_counted_base *>()(a.pi_, b.pi_); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
| { | ||||
|     if( pi_ == 0 || !pi_->add_ref_lock() ) | ||||
|     { | ||||
|         boost::throw_exception( boost::bad_weak_ptr() ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| # pragma warn .8027     // Functions containing try are not expanded inline | ||||
| #endif | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||
| @@ -1,182 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates | ||||
| // | ||||
| //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. | ||||
| //  Copyright (c) 2001, 2002 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/throw_exception.hpp> | ||||
| #include <boost/detail/atomic_count.hpp> | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
| # include <memory>          // for std::auto_ptr | ||||
| #endif | ||||
|  | ||||
| #include <algorithm>        // for std::swap | ||||
| #include <functional>       // for std::less | ||||
| #include <new>              // for std::bad_alloc | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> class shared_ptr | ||||
| { | ||||
| private: | ||||
|  | ||||
|     typedef detail::atomic_count count_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|     typedef T value_type; | ||||
|  | ||||
|     explicit shared_ptr(T * p = 0): px(p) | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try  // prevent leak if new throws | ||||
|         { | ||||
|             pn = new count_type(1); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             boost::checked_delete(p); | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pn = new count_type(1); | ||||
|  | ||||
|         if(pn == 0) | ||||
|         { | ||||
|             boost::checked_delete(p); | ||||
|             boost::throw_exception(std::bad_alloc()); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     ~shared_ptr() | ||||
|     { | ||||
|         if(--*pn == 0) | ||||
|         { | ||||
|             boost::checked_delete(px); | ||||
|             delete pn; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     shared_ptr(shared_ptr const & r): px(r.px)  // never throws | ||||
|     { | ||||
|         pn = r.pn; | ||||
|         ++*pn; | ||||
|     } | ||||
|  | ||||
|     shared_ptr & operator=(shared_ptr const & r) | ||||
|     { | ||||
|         shared_ptr(r).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     explicit shared_ptr(std::auto_ptr<T> & r) | ||||
|     {  | ||||
|         pn = new count_type(1); // may throw | ||||
|         px = r.release(); // fix: moved here to stop leak if new throws | ||||
|     }  | ||||
|  | ||||
|     shared_ptr & operator=(std::auto_ptr<T> & r) | ||||
|     { | ||||
|         shared_ptr(r).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     void reset(T * p = 0) | ||||
|     { | ||||
|         BOOST_ASSERT(p == 0 || p != px); | ||||
|         shared_ptr(p).swap(*this); | ||||
|     } | ||||
|  | ||||
|     T & operator*() const  // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(px != 0); | ||||
|         return *px; | ||||
|     } | ||||
|  | ||||
|     T * operator->() const  // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(px != 0); | ||||
|         return px; | ||||
|     } | ||||
|  | ||||
|     T * get() const  // never throws | ||||
|     { | ||||
|         return px; | ||||
|     } | ||||
|  | ||||
|     long use_count() const  // never throws | ||||
|     { | ||||
|         return *pn; | ||||
|     } | ||||
|  | ||||
|     bool unique() const  // never throws | ||||
|     { | ||||
|         return *pn == 1; | ||||
|     } | ||||
|      | ||||
|     void swap(shared_ptr<T> & other)  // never throws | ||||
|     { | ||||
|         std::swap(px, other.px); | ||||
|         std::swap(pn, other.pn); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     T * px;            // contained pointer | ||||
|     count_type * pn;   // ptr to reference counter | ||||
| }; | ||||
|  | ||||
| template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) | ||||
| { | ||||
|     return a.get() == b.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b) | ||||
| { | ||||
|     return std::less<T*>()(a.get(), b.get()); | ||||
| } | ||||
|  | ||||
| template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) | ||||
| { | ||||
|     a.swap(b); | ||||
| } | ||||
|  | ||||
| // get_pointer() enables boost::mem_fn to recognize shared_ptr | ||||
|  | ||||
| template<class T> inline T * get_pointer(shared_ptr<T> const & p) | ||||
| { | ||||
|     return p.get(); | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED | ||||
| @@ -1,69 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/sp_counted_base.hpp | ||||
| // | ||||
| //  Copyright 2005 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if defined( BOOST_SP_DISABLE_THREADS ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_PTHREADS ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_pt.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_gcc_x86.hpp> | ||||
|  | ||||
| //~ #elif defined( __MWERKS__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) | ||||
|  | ||||
| //~ # include <boost/detail/sp_counted_base_cw_x86.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_gcc_ia64.hpp> | ||||
|  | ||||
| #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_cw_ppc.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_gcc_ppc.hpp> | ||||
|  | ||||
| #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_w32.hpp> | ||||
|  | ||||
| #elif !defined( BOOST_HAS_THREADS ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
| # include <boost/detail/sp_counted_base_pt.hpp> | ||||
|  | ||||
| #else | ||||
|  | ||||
| // Use #define BOOST_DISABLE_THREADS to avoid the error | ||||
| # error Unrecognized threading platform | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED | ||||
| @@ -1,135 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/sp_counted_base_pt.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright 2004-2005 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <typeinfo> | ||||
| #include <pthread.h> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class sp_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base( sp_counted_base const & ); | ||||
|     sp_counted_base & operator= ( sp_counted_base const & ); | ||||
|  | ||||
|     long use_count_;        // #shared | ||||
|     long weak_count_;       // #weak + (#shared != 0) | ||||
|  | ||||
|     mutable pthread_mutex_t m_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) | ||||
|     { | ||||
| // HPUX 10.20 / DCE has a nonstandard pthread_mutex_init | ||||
|  | ||||
| #if defined(__hpux) && defined(_DECTHREADS_) | ||||
|         pthread_mutex_init( &m_, pthread_mutexattr_default ); | ||||
| #else | ||||
|         pthread_mutex_init( &m_, 0 ); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     virtual ~sp_counted_base() // nothrow | ||||
|     { | ||||
|         pthread_mutex_destroy( &m_ ); | ||||
|     } | ||||
|  | ||||
|     // dispose() is called when use_count_ drops to zero, to release | ||||
|     // the resources managed by *this. | ||||
|  | ||||
|     virtual void dispose() = 0; // nothrow | ||||
|  | ||||
|     // destroy() is called when weak_count_ drops to zero. | ||||
|  | ||||
|     virtual void destroy() // nothrow | ||||
|     { | ||||
|         delete this; | ||||
|     } | ||||
|  | ||||
|     virtual void * get_deleter( std::type_info const & ti ) = 0; | ||||
|  | ||||
|     void add_ref_copy() | ||||
|     { | ||||
|         pthread_mutex_lock( &m_ ); | ||||
|         ++use_count_; | ||||
|         pthread_mutex_unlock( &m_ ); | ||||
|     } | ||||
|  | ||||
|     bool add_ref_lock() // true on success | ||||
|     { | ||||
|         pthread_mutex_lock( &m_ ); | ||||
|         bool r = use_count_ == 0? false: ( ++use_count_, true ); | ||||
|         pthread_mutex_unlock( &m_ ); | ||||
|         return r; | ||||
|     } | ||||
|  | ||||
|     void release() // nothrow | ||||
|     { | ||||
|         pthread_mutex_lock( &m_ ); | ||||
|         long new_use_count = --use_count_; | ||||
|         pthread_mutex_unlock( &m_ ); | ||||
|  | ||||
|         if( new_use_count == 0 ) | ||||
|         { | ||||
|             dispose(); | ||||
|             weak_release(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void weak_add_ref() // nothrow | ||||
|     { | ||||
|         pthread_mutex_lock( &m_ ); | ||||
|         ++weak_count_; | ||||
|         pthread_mutex_unlock( &m_ ); | ||||
|     } | ||||
|  | ||||
|     void weak_release() // nothrow | ||||
|     { | ||||
|         pthread_mutex_lock( &m_ ); | ||||
|         long new_weak_count = --weak_count_; | ||||
|         pthread_mutex_unlock( &m_ ); | ||||
|  | ||||
|         if( new_weak_count == 0 ) | ||||
|         { | ||||
|             destroy(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     long use_count() const // nothrow | ||||
|     { | ||||
|         pthread_mutex_lock( &m_ ); | ||||
|         long r = use_count_; | ||||
|         pthread_mutex_unlock( &m_ ); | ||||
|  | ||||
|         return r; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED | ||||
| @@ -1,232 +0,0 @@ | ||||
| #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/sp_counted_impl.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright 2004-2005 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
| # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. | ||||
| #endif | ||||
|  | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/detail/sp_counted_base.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
| #include <boost/detail/quick_allocator.hpp> | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
| #include <memory>           // std::allocator | ||||
| #endif | ||||
|  | ||||
| #include <typeinfo>         // std::type_info in get_deleter | ||||
| #include <cstddef>          // std::size_t | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn ); | ||||
| void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn ); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<class X> class sp_counted_impl_p: public sp_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     X * px_; | ||||
|  | ||||
|     sp_counted_impl_p( sp_counted_impl_p const & ); | ||||
|     sp_counted_impl_p & operator= ( sp_counted_impl_p const & ); | ||||
|  | ||||
|     typedef sp_counted_impl_p<X> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     explicit sp_counted_impl_p( X * px ): px_( px ) | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_constructor_hook( px, sizeof(X), this ); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     virtual void dispose() // nothrow | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); | ||||
| #endif | ||||
|         boost::checked_delete( px_ ); | ||||
|     } | ||||
|  | ||||
|     virtual void * get_deleter( std::type_info const & ) | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) ); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return quick_allocator<this_type>::alloc(); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         quick_allocator<this_type>::dealloc( p ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| // | ||||
| // Borland's Codeguard trips up over the -Vx- option here: | ||||
| // | ||||
| #ifdef __CODEGUARD__ | ||||
| # pragma option push -Vx- | ||||
| #endif | ||||
|  | ||||
| template<class P, class D> class sp_counted_impl_pd: public sp_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     P ptr; // copy constructor must not throw | ||||
|     D del; // copy constructor must not throw | ||||
|  | ||||
|     sp_counted_impl_pd( sp_counted_impl_pd const & ); | ||||
|     sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); | ||||
|  | ||||
|     typedef sp_counted_impl_pd<P, D> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     // pre: d(p) must not throw | ||||
|  | ||||
|     sp_counted_impl_pd( P p, D d ): ptr(p), del(d) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     virtual void dispose() // nothrow | ||||
|     { | ||||
|         del( ptr ); | ||||
|     } | ||||
|  | ||||
|     virtual void * get_deleter( std::type_info const & ti ) | ||||
|     { | ||||
|         return ti == typeid(D)? &del: 0; | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) ); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return quick_allocator<this_type>::alloc(); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         quick_allocator<this_type>::dealloc( p ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     P p_; // copy constructor must not throw | ||||
|     D d_; // copy constructor must not throw | ||||
|     A a_; // copy constructor must not throw | ||||
|  | ||||
|     sp_counted_impl_pda( sp_counted_impl_pda const & ); | ||||
|     sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & ); | ||||
|  | ||||
|     typedef sp_counted_impl_pda<P, D, A> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     // pre: d( p ) must not throw | ||||
|  | ||||
|     sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     virtual void dispose() // nothrow | ||||
|     { | ||||
|         d_( p_ ); | ||||
|     } | ||||
|  | ||||
|     virtual void destroy() // nothrow | ||||
|     { | ||||
|         typedef typename A::template rebind< this_type >::other A2; | ||||
|  | ||||
|         A2 a2( a_ ); | ||||
|  | ||||
|         this->~this_type(); | ||||
|         a2.deallocate( this, 1 ); | ||||
|     } | ||||
|  | ||||
|     virtual void * get_deleter( std::type_info const & ti ) | ||||
|     { | ||||
|         return ti == typeid( D )? &d_: 0; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #ifdef __CODEGUARD__ | ||||
| # pragma option pop | ||||
| #endif | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED | ||||
| @@ -6,68 +6,13 @@ | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| //  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 | ||||
| // | ||||
| //  http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/weak_ptr.hpp> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> class enable_shared_from_this | ||||
| { | ||||
| protected: | ||||
|  | ||||
|     enable_shared_from_this() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     enable_shared_from_this(enable_shared_from_this const &) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     enable_shared_from_this & operator=(enable_shared_from_this const &) | ||||
|     { | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     ~enable_shared_from_this() | ||||
|     { | ||||
|     } | ||||
|  | ||||
| public: | ||||
|  | ||||
|     shared_ptr<T> shared_from_this() | ||||
|     { | ||||
|         shared_ptr<T> p(_internal_weak_this); | ||||
|         BOOST_ASSERT(p.get() == this); | ||||
|         return p; | ||||
|     } | ||||
|  | ||||
|     shared_ptr<T const> shared_from_this() const | ||||
|     { | ||||
|         shared_ptr<T const> p(_internal_weak_this); | ||||
|         BOOST_ASSERT(p.get() == this); | ||||
|         return p; | ||||
|     } | ||||
|  | ||||
| //  Note: No, you don't need to initialize _internal_weak_this | ||||
| // | ||||
| //  Please read the documentation, not the code | ||||
| // | ||||
| //  http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html | ||||
|  | ||||
|     typedef T _internal_element_type; // for bcc 5.5.1 | ||||
|     mutable weak_ptr<_internal_element_type> _internal_weak_this; | ||||
| }; | ||||
|  | ||||
| } // namespace boost | ||||
| #include <boost/smart_ptr/enable_shared_from_this.hpp> | ||||
|  | ||||
| #endif  // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED | ||||
|   | ||||
| @@ -1,29 +0,0 @@ | ||||
| // Copyright Peter Dimov and David Abrahams 2002. | ||||
| // 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) | ||||
| #ifndef GET_POINTER_DWA20021219_HPP | ||||
| # define GET_POINTER_DWA20021219_HPP | ||||
|  | ||||
| # include <memory> | ||||
|  | ||||
| namespace boost {  | ||||
|  | ||||
| // get_pointer(p) extracts a ->* capable pointer from p | ||||
|  | ||||
| template<class T> T * get_pointer(T * p) | ||||
| { | ||||
|     return p; | ||||
| } | ||||
|  | ||||
| // get_pointer(shared_ptr<T> const & p) has been moved to shared_ptr.hpp | ||||
|  | ||||
| template<class T> T * get_pointer(std::auto_ptr<T> const& p) | ||||
| { | ||||
|     return p.get(); | ||||
| } | ||||
|  | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // GET_POINTER_DWA20021219_HPP | ||||
| @@ -6,272 +6,13 @@ | ||||
| // | ||||
| //  Copyright (c) 2001, 2002 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| //  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 | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash | ||||
| # pragma warning(push) | ||||
| # pragma warning(disable:4284) // odd return type for operator-> | ||||
| #endif | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/detail/workaround.hpp> | ||||
|  | ||||
| #include <functional>           // for std::less | ||||
| #include <iosfwd>               // for std::basic_ostream | ||||
|  | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // | ||||
| //  intrusive_ptr | ||||
| // | ||||
| //  A smart pointer that uses intrusive reference counting. | ||||
| // | ||||
| //  Relies on unqualified calls to | ||||
| //   | ||||
| //      void intrusive_ptr_add_ref(T * p); | ||||
| //      void intrusive_ptr_release(T * p); | ||||
| // | ||||
| //          (p != 0) | ||||
| // | ||||
| //  The object is responsible for destroying itself. | ||||
| // | ||||
|  | ||||
| template<class T> class intrusive_ptr | ||||
| { | ||||
| private: | ||||
|  | ||||
|     typedef intrusive_ptr this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     intrusive_ptr(): p_(0) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     intrusive_ptr(T * p, bool add_ref = true): p_(p) | ||||
|     { | ||||
|         if(p_ != 0 && add_ref) intrusive_ptr_add_ref(p_); | ||||
|     } | ||||
|  | ||||
| #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
|  | ||||
|     template<class U> intrusive_ptr(intrusive_ptr<U> const & rhs): p_(rhs.get()) | ||||
|     { | ||||
|         if(p_ != 0) intrusive_ptr_add_ref(p_); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     intrusive_ptr(intrusive_ptr const & rhs): p_(rhs.p_) | ||||
|     { | ||||
|         if(p_ != 0) intrusive_ptr_add_ref(p_); | ||||
|     } | ||||
|  | ||||
|     ~intrusive_ptr() | ||||
|     { | ||||
|         if(p_ != 0) intrusive_ptr_release(p_); | ||||
|     } | ||||
|  | ||||
| #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
|  | ||||
|     template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs) | ||||
|     { | ||||
|         this_type(rhs).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     intrusive_ptr & operator=(intrusive_ptr const & rhs) | ||||
|     { | ||||
|         this_type(rhs).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     intrusive_ptr & operator=(T * rhs) | ||||
|     { | ||||
|         this_type(rhs).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     T * get() const | ||||
|     { | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     T & operator*() const | ||||
|     { | ||||
|         return *p_; | ||||
|     } | ||||
|  | ||||
|     T * operator->() const | ||||
|     { | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
| #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) | ||||
|  | ||||
|     operator bool () const | ||||
|     { | ||||
|         return p_ != 0; | ||||
|     } | ||||
|  | ||||
| #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) | ||||
|     typedef T * (this_type::*unspecified_bool_type)() const; | ||||
|      | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return p_ == 0? 0: &this_type::get; | ||||
|     } | ||||
|  | ||||
| #else  | ||||
|  | ||||
|     typedef T * this_type::*unspecified_bool_type; | ||||
|  | ||||
|     operator unspecified_bool_type () const | ||||
|     { | ||||
|         return p_ == 0? 0: &this_type::p_; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     // operator! is a Borland-specific workaround | ||||
|     bool operator! () const | ||||
|     { | ||||
|         return p_ == 0; | ||||
|     } | ||||
|  | ||||
|     void swap(intrusive_ptr & rhs) | ||||
|     { | ||||
|         T * tmp = p_; | ||||
|         p_ = rhs.p_; | ||||
|         rhs.p_ = tmp; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     T * p_; | ||||
| }; | ||||
|  | ||||
| template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) | ||||
| { | ||||
|     return a.get() == b.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) | ||||
| { | ||||
|     return a.get() == b; | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) | ||||
| { | ||||
|     return a.get() != b; | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) | ||||
| { | ||||
|     return a == b.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) | ||||
| { | ||||
|     return a != b.get(); | ||||
| } | ||||
|  | ||||
| #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 | ||||
|  | ||||
| // Resolve the ambiguity between our op!= and the one in rel_ops | ||||
|  | ||||
| template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) | ||||
| { | ||||
|     return std::less<T *>()(a.get(), b.get()); | ||||
| } | ||||
|  | ||||
| template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) | ||||
| { | ||||
|     lhs.swap(rhs); | ||||
| } | ||||
|  | ||||
| // mem_fn support | ||||
|  | ||||
| template<class T> T * get_pointer(intrusive_ptr<T> const & p) | ||||
| { | ||||
|     return p.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p) | ||||
| { | ||||
|     return static_cast<T *>(p.get()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p) | ||||
| { | ||||
|     return const_cast<T *>(p.get()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p) | ||||
| { | ||||
|     return dynamic_cast<T *>(p.get()); | ||||
| } | ||||
|  | ||||
| // operator<< | ||||
|  | ||||
| #if defined(__GNUC__) &&  (__GNUC__ < 3) | ||||
|  | ||||
| template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p) | ||||
| { | ||||
|     os << p.get(); | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| // in STLport's no-iostreams mode no iostream symbols can be used | ||||
| #ifndef _STLP_NO_IOSTREAMS | ||||
|  | ||||
| # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) | ||||
| // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL | ||||
| using std::basic_ostream; | ||||
| template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p) | ||||
| # else | ||||
| template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p) | ||||
| # endif  | ||||
| { | ||||
|     os << p.get(); | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| #endif // _STLP_NO_IOSTREAMS | ||||
|  | ||||
| #endif // __GNUC__ < 3 | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #ifdef BOOST_MSVC | ||||
| # pragma warning(pop) | ||||
| #endif     | ||||
| #include <boost/smart_ptr/intrusive_ptr.hpp> | ||||
|  | ||||
| #endif  // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED | ||||
|   | ||||
							
								
								
									
										16
									
								
								include/boost/make_shared.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								include/boost/make_shared.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED | ||||
| #define BOOST_MAKE_SHARED_HPP_INCLUDED | ||||
|  | ||||
| //  make_shared.hpp | ||||
| // | ||||
| //  Copyright (c) 2007, 2008 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
|  | ||||
| #include <boost/smart_ptr/make_shared.hpp> | ||||
|  | ||||
| #endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED | ||||
							
								
								
									
										13
									
								
								include/boost/make_unique.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/boost/make_unique.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /* | ||||
| Copyright 2014 Glen Joseph Fernandes | ||||
| (glenjofe@gmail.com) | ||||
|  | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| (http://www.boost.org/LICENSE_1_0.txt) | ||||
| */ | ||||
| #ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED | ||||
| #define BOOST_MAKE_UNIQUE_HPP_INCLUDED | ||||
|  | ||||
| #include <boost/smart_ptr/make_unique.hpp> | ||||
|  | ||||
| #endif | ||||
| @@ -1,6 +1,6 @@ | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // | ||||
| // (C) Copyright Ion Gazta<EFBFBD>aga 2005.  | ||||
| // (C) Copyright Ion Gaztanaga 2005.  | ||||
| // 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) | ||||
| @@ -10,36 +10,101 @@ | ||||
| #ifndef BOOST_POINTER_CAST_HPP | ||||
| #define BOOST_POINTER_CAST_HPP | ||||
|  | ||||
| #include <memory> | ||||
| #include <type_traits> | ||||
|  | ||||
| namespace boost {  | ||||
|  | ||||
| //static_pointer_cast overload for raw pointers | ||||
| template<class T, class U> | ||||
| inline T* static_pointer_cast(U *ptr) | ||||
| inline T* static_pointer_cast(U *ptr) noexcept | ||||
| {   | ||||
|    return static_cast<T*>(ptr); | ||||
| } | ||||
|  | ||||
| //dynamic_pointer_cast overload for raw pointers | ||||
| template<class T, class U> | ||||
| inline T* dynamic_pointer_cast(U *ptr) | ||||
| inline T* dynamic_pointer_cast(U *ptr) noexcept | ||||
| {   | ||||
|    return dynamic_cast<T*>(ptr); | ||||
| } | ||||
|  | ||||
| //const_pointer_cast overload for raw pointers | ||||
| template<class T, class U> | ||||
| inline T* const_pointer_cast(U *ptr) | ||||
| inline T* const_pointer_cast(U *ptr) noexcept | ||||
| {   | ||||
|    return const_cast<T*>(ptr); | ||||
| } | ||||
|  | ||||
| //reinterpret_pointer_cast overload for raw pointers | ||||
| template<class T, class U> | ||||
| inline T* reinterpret_pointer_cast(U *ptr) | ||||
| inline T* reinterpret_pointer_cast(U *ptr) noexcept | ||||
| {   | ||||
|    return reinterpret_cast<T*>(ptr); | ||||
| } | ||||
|  | ||||
| //static_pointer_cast overload for std::shared_ptr | ||||
| using std::static_pointer_cast; | ||||
|  | ||||
| //dynamic_pointer_cast overload for std::shared_ptr | ||||
| using std::dynamic_pointer_cast; | ||||
|  | ||||
| //const_pointer_cast overload for std::shared_ptr | ||||
| using std::const_pointer_cast; | ||||
|  | ||||
| //reinterpret_pointer_cast overload for std::shared_ptr | ||||
| template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) noexcept | ||||
| { | ||||
|     (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); | ||||
|  | ||||
|     typedef typename std::shared_ptr<T>::element_type E; | ||||
|  | ||||
|     E * p = reinterpret_cast< E* >( r.get() ); | ||||
|     return std::shared_ptr<T>( r, p ); | ||||
| } | ||||
|  | ||||
| //static_pointer_cast overload for std::unique_ptr | ||||
| template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_ptr<U> && r ) noexcept | ||||
| { | ||||
|     (void) static_cast< T* >( static_cast< U* >( 0 ) ); | ||||
|  | ||||
|     typedef typename std::unique_ptr<T>::element_type E; | ||||
|  | ||||
|     return std::unique_ptr<T>( static_cast<E*>( r.release() ) ); | ||||
| } | ||||
|  | ||||
| //dynamic_pointer_cast overload for std::unique_ptr | ||||
| template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) noexcept | ||||
| { | ||||
|     (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); | ||||
|  | ||||
|     static_assert( std::has_virtual_destructor<T>::value, "The target of dynamic_pointer_cast must have a virtual destructor." ); | ||||
|  | ||||
|     T * p = dynamic_cast<T*>( r.get() ); | ||||
|     if( p ) r.release(); | ||||
|     return std::unique_ptr<T>( p ); | ||||
| } | ||||
|  | ||||
| //const_pointer_cast overload for std::unique_ptr | ||||
| template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_ptr<U> && r ) noexcept | ||||
| { | ||||
|     (void) const_cast< T* >( static_cast< U* >( 0 ) ); | ||||
|  | ||||
|     typedef typename std::unique_ptr<T>::element_type E; | ||||
|  | ||||
|     return std::unique_ptr<T>( const_cast<E*>( r.release() ) ); | ||||
| } | ||||
|  | ||||
| //reinterpret_pointer_cast overload for std::unique_ptr | ||||
| template<class T, class U> std::unique_ptr<T> reinterpret_pointer_cast( std::unique_ptr<U> && r ) noexcept | ||||
| { | ||||
|     (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); | ||||
|  | ||||
|     typedef typename std::unique_ptr<T>::element_type E; | ||||
|  | ||||
|     return std::unique_ptr<T>( reinterpret_cast<E*>( r.release() ) ); | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif   //BOOST_POINTER_CAST_HPP | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| // | ||||
| //  pointer_to_other.hpp | ||||
| // | ||||
| //  (C) Copyright Ion Gazta<EFBFBD>aga 2005. | ||||
| //  (C) Copyright Ion Gaztanaga 2005. | ||||
| //  Copyright (c) 2005 Peter Dimov. | ||||
| // | ||||
| //  Distributed under the Boost Software License, Version 1.0. | ||||
| @@ -12,7 +12,7 @@ | ||||
| //  (See accompanying file LICENSE_1_0.txt or copy at  | ||||
| //  http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/pointer_to_other.html | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| namespace boost | ||||
|   | ||||
| @@ -8,128 +8,8 @@ | ||||
| //  accompanying file LICENSE_1_0.txt or copy at | ||||
| //  http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| //  http://www.boost.org/libs/smart_ptr/scoped_array.htm | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/config.hpp>   // in case ptrdiff_t not in std | ||||
|  | ||||
| #include <boost/detail/workaround.hpp> | ||||
|  | ||||
| #include <cstddef>            // for std::ptrdiff_t | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // Debug hooks | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| void sp_array_constructor_hook(void * p); | ||||
| void sp_array_destructor_hook(void * p); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| //  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to | ||||
| //  is guaranteed, either on destruction of the scoped_array or via an explicit | ||||
| //  reset(). Use shared_array or std::vector if your needs are more complex. | ||||
|  | ||||
| template<class T> class scoped_array // noncopyable | ||||
| { | ||||
| private: | ||||
|  | ||||
|     T * ptr; | ||||
|  | ||||
|     scoped_array(scoped_array const &); | ||||
|     scoped_array & operator=(scoped_array const &); | ||||
|  | ||||
|     typedef scoped_array<T> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     explicit scoped_array(T * p = 0) : ptr(p) // never throws | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_array_constructor_hook(ptr); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     ~scoped_array() // never throws | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_array_destructor_hook(ptr); | ||||
| #endif | ||||
|         boost::checked_array_delete(ptr); | ||||
|     } | ||||
|  | ||||
|     void reset(T * p = 0) // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors | ||||
|         this_type(p).swap(*this); | ||||
|     } | ||||
|  | ||||
|     T & operator[](std::ptrdiff_t i) const // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(ptr != 0); | ||||
|         BOOST_ASSERT(i >= 0); | ||||
|         return ptr[i]; | ||||
|     } | ||||
|  | ||||
|     T * get() const // never throws | ||||
|     { | ||||
|         return ptr; | ||||
|     } | ||||
|  | ||||
|     // implicit conversion to "bool" | ||||
|  | ||||
| #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) | ||||
|  | ||||
|     operator bool () const | ||||
|     { | ||||
|         return ptr != 0; | ||||
|     } | ||||
|  | ||||
| #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) | ||||
|     typedef T * (this_type::*unspecified_bool_type)() const; | ||||
|      | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return ptr == 0? 0: &this_type::get; | ||||
|     } | ||||
|  | ||||
| #else  | ||||
|  | ||||
|     typedef T * this_type::*unspecified_bool_type; | ||||
|  | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return ptr == 0? 0: &this_type::ptr; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     bool operator! () const // never throws | ||||
|     { | ||||
|         return ptr == 0; | ||||
|     } | ||||
|  | ||||
|     void swap(scoped_array & b) // never throws | ||||
|     { | ||||
|         T * tmp = b.ptr; | ||||
|         b.ptr = ptr; | ||||
|         ptr = tmp; | ||||
|     } | ||||
|  | ||||
| }; | ||||
|  | ||||
| template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws | ||||
| { | ||||
|     a.swap(b); | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
| #include <boost/smart_ptr/scoped_array.hpp> | ||||
|  | ||||
| #endif  // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED | ||||
|   | ||||
| @@ -8,150 +8,8 @@ | ||||
| //  accompanying file LICENSE_1_0.txt or copy at | ||||
| //  http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| //  http://www.boost.org/libs/smart_ptr/scoped_ptr.htm | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/detail/workaround.hpp> | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
| # include <memory>          // for std::auto_ptr | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // Debug hooks | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| void sp_scalar_constructor_hook(void * p); | ||||
| void sp_scalar_destructor_hook(void * p); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| //  scoped_ptr mimics a built-in pointer except that it guarantees deletion | ||||
| //  of the object pointed to, either on destruction of the scoped_ptr or via | ||||
| //  an explicit reset(). scoped_ptr is a simple solution for simple needs; | ||||
| //  use shared_ptr or std::auto_ptr if your needs are more complex. | ||||
|  | ||||
| template<class T> class scoped_ptr // noncopyable | ||||
| { | ||||
| private: | ||||
|  | ||||
|     T * ptr; | ||||
|  | ||||
|     scoped_ptr(scoped_ptr const &); | ||||
|     scoped_ptr & operator=(scoped_ptr const &); | ||||
|  | ||||
|     typedef scoped_ptr<T> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     explicit scoped_ptr(T * p = 0): ptr(p) // never throws | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_constructor_hook(ptr); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     explicit scoped_ptr(std::auto_ptr<T> p): ptr(p.release()) // never throws | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_constructor_hook(ptr); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     ~scoped_ptr() // never throws | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_destructor_hook(ptr); | ||||
| #endif | ||||
|         boost::checked_delete(ptr); | ||||
|     } | ||||
|  | ||||
|     void reset(T * p = 0) // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(p == 0 || p != ptr); // catch self-reset errors | ||||
|         this_type(p).swap(*this); | ||||
|     } | ||||
|  | ||||
|     T & operator*() const // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(ptr != 0); | ||||
|         return *ptr; | ||||
|     } | ||||
|  | ||||
|     T * operator->() const // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(ptr != 0); | ||||
|         return ptr; | ||||
|     } | ||||
|  | ||||
|     T * get() const // never throws | ||||
|     { | ||||
|         return ptr; | ||||
|     } | ||||
|  | ||||
|     // implicit conversion to "bool" | ||||
|  | ||||
| #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) | ||||
|  | ||||
|     operator bool () const | ||||
|     { | ||||
|         return ptr != 0; | ||||
|     } | ||||
|  | ||||
| #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) | ||||
|     typedef T * (this_type::*unspecified_bool_type)() const; | ||||
|      | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return ptr == 0? 0: &this_type::get; | ||||
|     } | ||||
|  | ||||
| #else  | ||||
|     typedef T * this_type::*unspecified_bool_type; | ||||
|  | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return ptr == 0? 0: &this_type::ptr; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     bool operator! () const // never throws | ||||
|     { | ||||
|         return ptr == 0; | ||||
|     } | ||||
|  | ||||
|     void swap(scoped_ptr & b) // never throws | ||||
|     { | ||||
|         T * tmp = b.ptr; | ||||
|         b.ptr = ptr; | ||||
|         ptr = tmp; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws | ||||
| { | ||||
|     a.swap(b); | ||||
| } | ||||
|  | ||||
| // get_pointer(p) is a generic way to say p.get() | ||||
|  | ||||
| template<class T> inline T * get_pointer(scoped_ptr<T> const & p) | ||||
| { | ||||
|     return p.get(); | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
| #include <boost/smart_ptr/scoped_ptr.hpp> | ||||
|  | ||||
| #endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED | ||||
|   | ||||
| @@ -11,167 +11,9 @@ | ||||
| //  accompanying file LICENSE_1_0.txt or copy at | ||||
| //  http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp>   // for broken compiler workarounds | ||||
|  | ||||
| #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
| #include <boost/detail/shared_array_nmt.hpp> | ||||
| #else | ||||
|  | ||||
| #include <memory>             // TR1 cyclic inclusion fix | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
|  | ||||
| #include <boost/detail/shared_count.hpp> | ||||
| #include <boost/detail/workaround.hpp> | ||||
|  | ||||
| #include <cstddef>            // for std::ptrdiff_t | ||||
| #include <algorithm>          // for std::swap | ||||
| #include <functional>         // for std::less | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // | ||||
| //  shared_array | ||||
| // | ||||
| //  shared_array extends shared_ptr to arrays. | ||||
| //  The array pointed to is deleted when the last shared_array pointing to it | ||||
| //  is destroyed or reset. | ||||
| // | ||||
|  | ||||
| template<class T> class shared_array | ||||
| { | ||||
| private: | ||||
|  | ||||
|     // Borland 5.5.1 specific workarounds | ||||
|     typedef checked_array_deleter<T> deleter; | ||||
|     typedef shared_array<T> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|  | ||||
|     explicit shared_array(T * p = 0): px(p), pn(p, deleter()) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Requirements: D's copy constructor must not throw | ||||
|     // | ||||
|     // shared_array will release p by calling d(p) | ||||
|     // | ||||
|  | ||||
|     template<class D> shared_array(T * p, D d): px(p), pn(p, d) | ||||
|     { | ||||
|     } | ||||
|  | ||||
| //  generated copy constructor, assignment, destructor are fine | ||||
|  | ||||
|     void reset(T * p = 0) | ||||
|     { | ||||
|         BOOST_ASSERT(p == 0 || p != px); | ||||
|         this_type(p).swap(*this); | ||||
|     } | ||||
|  | ||||
|     template <class D> void reset(T * p, D d) | ||||
|     { | ||||
|         this_type(p, d).swap(*this); | ||||
|     } | ||||
|  | ||||
|     T & operator[] (std::ptrdiff_t i) const // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(px != 0); | ||||
|         BOOST_ASSERT(i >= 0); | ||||
|         return px[i]; | ||||
|     } | ||||
|      | ||||
|     T * get() const // never throws | ||||
|     { | ||||
|         return px; | ||||
|     } | ||||
|  | ||||
|     // implicit conversion to "bool" | ||||
|  | ||||
| #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530) | ||||
|  | ||||
|     operator bool () const | ||||
|     { | ||||
|         return px != 0; | ||||
|     } | ||||
|  | ||||
| #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) | ||||
|     typedef T * (this_type::*unspecified_bool_type)() const; | ||||
|      | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return px == 0? 0: &this_type::get; | ||||
|     } | ||||
|  | ||||
| #else  | ||||
|  | ||||
|     typedef T * this_type::*unspecified_bool_type; | ||||
|  | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return px == 0? 0: &this_type::px; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     bool operator! () const // never throws | ||||
|     { | ||||
|         return px == 0; | ||||
|     } | ||||
|  | ||||
|     bool unique() const // never throws | ||||
|     { | ||||
|         return pn.unique(); | ||||
|     } | ||||
|  | ||||
|     long use_count() const // never throws | ||||
|     { | ||||
|         return pn.use_count(); | ||||
|     } | ||||
|  | ||||
|     void swap(shared_array<T> & other) // never throws | ||||
|     { | ||||
|         std::swap(px, other.px); | ||||
|         pn.swap(other.pn); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     T * px;                     // contained pointer | ||||
|     detail::shared_count pn;    // reference counter | ||||
|  | ||||
| };  // shared_array | ||||
|  | ||||
| template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws | ||||
| { | ||||
|     return a.get() == b.get(); | ||||
| } | ||||
|  | ||||
| template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws | ||||
| { | ||||
|     return std::less<T*>()(a.get(), b.get()); | ||||
| } | ||||
|  | ||||
| template<class T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws | ||||
| { | ||||
|     a.swap(b); | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
| #include <boost/smart_ptr/shared_array.hpp> | ||||
|  | ||||
| #endif  // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED | ||||
|   | ||||
| @@ -5,554 +5,15 @@ | ||||
| //  shared_ptr.hpp | ||||
| // | ||||
| //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. | ||||
| //  Copyright (c) 2001-2006 Peter Dimov | ||||
| //  Copyright (c) 2001-2008 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp>   // for broken compiler workarounds | ||||
|  | ||||
| #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
| #include <boost/detail/shared_ptr_nmt.hpp> | ||||
| #else | ||||
|  | ||||
| #include <memory>               // for std::auto_ptr | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/checked_delete.hpp> | ||||
| #include <boost/throw_exception.hpp> | ||||
| #include <boost/detail/shared_count.hpp> | ||||
| #include <boost/detail/workaround.hpp> | ||||
|  | ||||
| #include <algorithm>            // for std::swap | ||||
| #include <functional>           // for std::less | ||||
| #include <typeinfo>             // for std::bad_cast | ||||
| #include <iosfwd>               // for std::basic_ostream | ||||
|  | ||||
| #ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash | ||||
| # pragma warning(push) | ||||
| # pragma warning(disable:4284) // odd return type for operator-> | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> class weak_ptr; | ||||
| template<class T> class enable_shared_from_this; | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| struct static_cast_tag {}; | ||||
| struct const_cast_tag {}; | ||||
| struct dynamic_cast_tag {}; | ||||
| struct polymorphic_cast_tag {}; | ||||
|  | ||||
| template<class T> struct shared_ptr_traits | ||||
| { | ||||
|     typedef T & reference; | ||||
| }; | ||||
|  | ||||
| template<> struct shared_ptr_traits<void> | ||||
| { | ||||
|     typedef void reference; | ||||
| }; | ||||
|  | ||||
| #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) | ||||
|  | ||||
| template<> struct shared_ptr_traits<void const> | ||||
| { | ||||
|     typedef void reference; | ||||
| }; | ||||
|  | ||||
| template<> struct shared_ptr_traits<void volatile> | ||||
| { | ||||
|     typedef void reference; | ||||
| }; | ||||
|  | ||||
| template<> struct shared_ptr_traits<void const volatile> | ||||
| { | ||||
|     typedef void reference; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| // enable_shared_from_this support | ||||
|  | ||||
| template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px ) | ||||
| { | ||||
|     if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn); | ||||
| } | ||||
|  | ||||
| #ifdef sgi | ||||
| // Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed | ||||
| # pragma set woff 3506 | ||||
| #endif | ||||
|  | ||||
| inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) | ||||
| { | ||||
| } | ||||
|  | ||||
| #ifdef sgi | ||||
| # pragma reset woff 3506 | ||||
| #endif | ||||
|  | ||||
| #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) | ||||
|  | ||||
| // rvalue auto_ptr support based on a technique by Dave Abrahams | ||||
|  | ||||
| template< class T, class R > struct sp_enable_if_auto_ptr | ||||
| { | ||||
| }; | ||||
|  | ||||
| template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > | ||||
| { | ||||
|     typedef R type; | ||||
| };  | ||||
|  | ||||
| #endif | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
|  | ||||
| // | ||||
| //  shared_ptr | ||||
| // | ||||
| //  An enhanced relative of scoped_ptr with reference counted copy semantics. | ||||
| //  The object pointed to is deleted when the last shared_ptr pointing to it | ||||
| //  is destroyed or reset. | ||||
| // | ||||
|  | ||||
| template<class T> class shared_ptr | ||||
| { | ||||
| private: | ||||
|  | ||||
|     // Borland 5.5.1 specific workaround | ||||
|     typedef shared_ptr<T> this_type; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     typedef T element_type; | ||||
|     typedef T value_type; | ||||
|     typedef T * pointer; | ||||
|     typedef typename boost::detail::shared_ptr_traits<T>::reference reference; | ||||
|  | ||||
|     shared_ptr(): px(0), pn() // never throws in 1.30+ | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> | ||||
|     explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete | ||||
|     { | ||||
|         boost::detail::sp_enable_shared_from_this( pn, p, p ); | ||||
|     } | ||||
|  | ||||
|     // | ||||
|     // Requirements: D's copy constructor must not throw | ||||
|     // | ||||
|     // shared_ptr will release p by calling d(p) | ||||
|     // | ||||
|  | ||||
|     template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d) | ||||
|     { | ||||
|         boost::detail::sp_enable_shared_from_this( pn, p, p ); | ||||
|     } | ||||
|  | ||||
|     // As above, but with allocator. A's copy constructor shall not throw. | ||||
|  | ||||
|     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) | ||||
|     { | ||||
|         boost::detail::sp_enable_shared_from_this( pn, p, p ); | ||||
|     } | ||||
|  | ||||
| //  generated copy constructor, assignment, destructor are fine... | ||||
|  | ||||
| //  except that Borland C++ has a bug, and g++ with -Wsynth warns | ||||
| #if defined(__BORLANDC__) || defined(__GNUC__) | ||||
|  | ||||
|     shared_ptr & operator=(shared_ptr const & r) // never throws | ||||
|     { | ||||
|         px = r.px; | ||||
|         pn = r.pn; // shared_count::op= doesn't throw | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     template<class Y> | ||||
|     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw | ||||
|     { | ||||
|         // it is now safe to copy r.px, as pn(r.pn) did not throw | ||||
|         px = r.px; | ||||
|     } | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) | ||||
|     { | ||||
|         if(px == 0) // need to allocate new counter -- the cast failed | ||||
|         { | ||||
|             pn = boost::detail::shared_count(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn) | ||||
|     { | ||||
|         if(px == 0) | ||||
|         { | ||||
|             boost::throw_exception(std::bad_cast()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     template<class Y> | ||||
|     explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn() | ||||
|     { | ||||
|         Y * tmp = r.get(); | ||||
|         pn = boost::detail::shared_count(r); | ||||
|         boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); | ||||
|     } | ||||
|  | ||||
| #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||
|  | ||||
|     template<class Ap> | ||||
|     explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn() | ||||
|     { | ||||
|         typename Ap::element_type * tmp = r.get(); | ||||
|         pn = boost::detail::shared_count( r ); | ||||
|         boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); | ||||
|     } | ||||
|  | ||||
|  | ||||
| #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| #endif // BOOST_NO_AUTO_PTR | ||||
|  | ||||
| #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws | ||||
|     { | ||||
|         px = r.px; | ||||
|         pn = r.pn; // shared_count::op= doesn't throw | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     template<class Y> | ||||
|     shared_ptr & operator=( std::auto_ptr<Y> & r ) | ||||
|     { | ||||
|         this_type(r).swap(*this); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
| #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) | ||||
|  | ||||
|     template<class Ap> | ||||
|     typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) | ||||
|     { | ||||
|         this_type( r ).swap( *this ); | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|  | ||||
| #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| #endif // BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     void reset() // never throws in 1.30+ | ||||
|     { | ||||
|         this_type().swap(*this); | ||||
|     } | ||||
|  | ||||
|     template<class Y> void reset(Y * p) // Y must be complete | ||||
|     { | ||||
|         BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors | ||||
|         this_type(p).swap(*this); | ||||
|     } | ||||
|  | ||||
|     template<class Y, class D> void reset( Y * p, D d ) | ||||
|     { | ||||
|         this_type( p, d ).swap( *this ); | ||||
|     } | ||||
|  | ||||
|     template<class Y, class D, class A> void reset( Y * p, D d, A a ) | ||||
|     { | ||||
|         this_type( p, d, a ).swap( *this ); | ||||
|     } | ||||
|  | ||||
|     reference operator* () const // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(px != 0); | ||||
|         return *px; | ||||
|     } | ||||
|  | ||||
|     T * operator-> () const // never throws | ||||
|     { | ||||
|         BOOST_ASSERT(px != 0); | ||||
|         return px; | ||||
|     } | ||||
|      | ||||
|     T * get() const // never throws | ||||
|     { | ||||
|         return px; | ||||
|     } | ||||
|  | ||||
|     // implicit conversion to "bool" | ||||
|  | ||||
| #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) | ||||
|  | ||||
|     operator bool () const | ||||
|     { | ||||
|         return px != 0; | ||||
|     } | ||||
|  | ||||
| #elif defined( _MANAGED ) | ||||
|  | ||||
|     static void unspecified_bool( this_type*** ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     typedef void (*unspecified_bool_type)( this_type*** ); | ||||
|  | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return px == 0? 0: unspecified_bool; | ||||
|     } | ||||
|  | ||||
| #elif \ | ||||
|     ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ | ||||
|     ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) | ||||
|  | ||||
|     typedef T * (this_type::*unspecified_bool_type)() const; | ||||
|      | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return px == 0? 0: &this_type::get; | ||||
|     } | ||||
|  | ||||
| #else  | ||||
|  | ||||
|     typedef T * this_type::*unspecified_bool_type; | ||||
|  | ||||
|     operator unspecified_bool_type() const // never throws | ||||
|     { | ||||
|         return px == 0? 0: &this_type::px; | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     // operator! is redundant, but some compilers need it | ||||
|  | ||||
|     bool operator! () const // never throws | ||||
|     { | ||||
|         return px == 0; | ||||
|     } | ||||
|  | ||||
|     bool unique() const // never throws | ||||
|     { | ||||
|         return pn.unique(); | ||||
|     } | ||||
|  | ||||
|     long use_count() const // never throws | ||||
|     { | ||||
|         return pn.use_count(); | ||||
|     } | ||||
|  | ||||
|     void swap(shared_ptr<T> & other) // never throws | ||||
|     { | ||||
|         std::swap(px, other.px); | ||||
|         pn.swap(other.pn); | ||||
|     } | ||||
|  | ||||
|     template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const | ||||
|     { | ||||
|         return pn < rhs.pn; | ||||
|     } | ||||
|  | ||||
|     void * _internal_get_deleter(std::type_info const & ti) const | ||||
|     { | ||||
|         return pn.get_deleter(ti); | ||||
|     } | ||||
|  | ||||
| // Tasteless as this may seem, making all members public allows member templates | ||||
| // to work in the absence of member template friends. (Matthew Langston) | ||||
|  | ||||
| #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS | ||||
|  | ||||
| private: | ||||
|  | ||||
|     template<class Y> friend class shared_ptr; | ||||
|     template<class Y> friend class weak_ptr; | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     T * px;                     // contained pointer | ||||
|     boost::detail::shared_count pn;    // reference counter | ||||
|  | ||||
| };  // shared_ptr | ||||
|  | ||||
| template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) | ||||
| { | ||||
|     return a.get() == b.get(); | ||||
| } | ||||
|  | ||||
| template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 | ||||
|  | ||||
| // Resolve the ambiguity between our op!= and the one in rel_ops | ||||
|  | ||||
| template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) | ||||
| { | ||||
|     return a.get() != b.get(); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) | ||||
| { | ||||
|     return a._internal_less(b); | ||||
| } | ||||
|  | ||||
| template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) | ||||
| { | ||||
|     a.swap(b); | ||||
| } | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) | ||||
| { | ||||
|     return shared_ptr<T>(r, boost::detail::static_cast_tag()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) | ||||
| { | ||||
|     return shared_ptr<T>(r, boost::detail::const_cast_tag()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) | ||||
| { | ||||
|     return shared_ptr<T>(r, boost::detail::dynamic_cast_tag()); | ||||
| } | ||||
|  | ||||
| // shared_*_cast names are deprecated. Use *_pointer_cast instead. | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r) | ||||
| { | ||||
|     return shared_ptr<T>(r, boost::detail::static_cast_tag()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r) | ||||
| { | ||||
|     return shared_ptr<T>(r, boost::detail::dynamic_cast_tag()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r) | ||||
| { | ||||
|     return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag()); | ||||
| } | ||||
|  | ||||
| template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r) | ||||
| { | ||||
|     BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get()); | ||||
|     return shared_static_cast<T>(r); | ||||
| } | ||||
|  | ||||
| // get_pointer() enables boost::mem_fn to recognize shared_ptr | ||||
|  | ||||
| template<class T> inline T * get_pointer(shared_ptr<T> const & p) | ||||
| { | ||||
|     return p.get(); | ||||
| } | ||||
|  | ||||
| // operator<< | ||||
|  | ||||
| #if defined(__GNUC__) &&  (__GNUC__ < 3) | ||||
|  | ||||
| template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p) | ||||
| { | ||||
|     os << p.get(); | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| // in STLport's no-iostreams mode no iostream symbols can be used | ||||
| #ifndef _STLP_NO_IOSTREAMS | ||||
|  | ||||
| # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) | ||||
| // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL | ||||
| using std::basic_ostream; | ||||
| template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p) | ||||
| # else | ||||
| template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p) | ||||
| # endif  | ||||
| { | ||||
|     os << p.get(); | ||||
|     return os; | ||||
| } | ||||
|  | ||||
| #endif // _STLP_NO_IOSTREAMS | ||||
|  | ||||
| #endif // __GNUC__ < 3 | ||||
|  | ||||
| // get_deleter (experimental) | ||||
|  | ||||
| #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ | ||||
|     ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ | ||||
|     ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) | ||||
|  | ||||
| // g++ 2.9x doesn't allow static_cast<X const *>(void *) | ||||
| // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it | ||||
|  | ||||
| template<class D, class T> D * get_deleter(shared_ptr<T> const & p) | ||||
| { | ||||
|     void const * q = p._internal_get_deleter(typeid(D)); | ||||
|     return const_cast<D *>(static_cast<D const *>(q)); | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| template<class D, class T> D * get_deleter(shared_ptr<T> const & p) | ||||
| { | ||||
|     return static_cast<D *>(p._internal_get_deleter(typeid(D))); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #ifdef BOOST_MSVC | ||||
| # pragma warning(pop) | ||||
| #endif     | ||||
|  | ||||
| #endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
| #include <boost/smart_ptr/shared_ptr.hpp> | ||||
|  | ||||
| #endif  // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED | ||||
|   | ||||
| @@ -1,3 +1,6 @@ | ||||
| #ifndef BOOST_SMART_PTR_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  smart_ptr.hpp | ||||
| // | ||||
| @@ -8,18 +11,16 @@ | ||||
| //  Software License, Version 1.0. (See accompanying file | ||||
| //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| //  http://www.boost.org/libs/smart_ptr/smart_ptr.htm | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #include <boost/scoped_ptr.hpp> | ||||
| #include <boost/scoped_array.hpp> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/shared_array.hpp> | ||||
| #include <boost/weak_ptr.hpp> | ||||
| #include <boost/intrusive_ptr.hpp> | ||||
| #include <boost/enable_shared_from_this.hpp> | ||||
| #include <boost/make_shared.hpp> | ||||
|  | ||||
| #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
| # include <boost/weak_ptr.hpp> | ||||
| # include <boost/intrusive_ptr.hpp> | ||||
| # include <boost/enable_shared_from_this.hpp> | ||||
| #endif | ||||
| #endif // #ifndef BOOST_SMART_PTR_HPP_INCLUDED | ||||
|   | ||||
							
								
								
									
										180
									
								
								include/boost/smart_ptr/allocate_local_shared_array.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								include/boost/smart_ptr/allocate_local_shared_array.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| /* | ||||
| Copyright 2017-2019 Glen Joseph Fernandes | ||||
| (glenjofe@gmail.com) | ||||
|  | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| (http://www.boost.org/LICENSE_1_0.txt) | ||||
| */ | ||||
| #ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP | ||||
| #define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP | ||||
|  | ||||
| #include <boost/smart_ptr/allocate_shared_array.hpp> | ||||
| #include <boost/smart_ptr/local_shared_ptr.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_type_traits.hpp> | ||||
| #include <type_traits> | ||||
|  | ||||
| namespace boost { | ||||
| namespace detail { | ||||
|  | ||||
| class BOOST_SYMBOL_VISIBLE lsp_array_base | ||||
|     : public local_counted_base { | ||||
| public: | ||||
|     void set(sp_counted_base* base) noexcept { | ||||
|         count_ = shared_count(base); | ||||
|     } | ||||
|  | ||||
|     void local_cb_destroy() noexcept override { | ||||
|         shared_count().swap(count_); | ||||
|     } | ||||
|  | ||||
|     shared_count local_cb_get_shared_count() const | ||||
|         noexcept override { | ||||
|         return count_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     shared_count count_; | ||||
| }; | ||||
|  | ||||
| template<class A> | ||||
| class lsp_array_state | ||||
|     : public sp_array_state<A> { | ||||
| public: | ||||
|     template<class U> | ||||
|     lsp_array_state(const U& other, std::size_t size) noexcept | ||||
|         : sp_array_state<A>(other, size) { } | ||||
|  | ||||
|     lsp_array_base& base() noexcept { | ||||
|         return base_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     lsp_array_base base_; | ||||
| }; | ||||
|  | ||||
| template<class A, std::size_t N> | ||||
| class lsp_size_array_state | ||||
|     : public sp_size_array_state<A, N> { | ||||
| public: | ||||
|     template<class U> | ||||
|     lsp_size_array_state(const U& other, std::size_t size) noexcept | ||||
|         : sp_size_array_state<A, N>(other, size) { } | ||||
|  | ||||
|     lsp_array_base& base() noexcept { | ||||
|         return base_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     lsp_array_base base_; | ||||
| }; | ||||
|  | ||||
| } /* detail */ | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, | ||||
|     local_shared_ptr<T> >::type | ||||
| allocate_local_shared(const A& allocator, std::size_t count) | ||||
| { | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::lsp_array_state<other> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count); | ||||
|     detail::lsp_array_base& local = node->state().base(); | ||||
|     local.set(node); | ||||
|     result.release(); | ||||
|     return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start, | ||||
|         &local); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, | ||||
|     local_shared_ptr<T> >::type | ||||
| allocate_local_shared(const A& allocator) | ||||
| { | ||||
|     enum { | ||||
|         count = std::extent<T>::value | ||||
|     }; | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::lsp_size_array_state<other, count> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count); | ||||
|     detail::lsp_array_base& local = node->state().base(); | ||||
|     local.set(node); | ||||
|     result.release(); | ||||
|     return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start, | ||||
|         &local); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, | ||||
|     local_shared_ptr<T> >::type | ||||
| allocate_local_shared(const A& allocator, std::size_t count, | ||||
|     const typename std::remove_extent<T>::type& value) | ||||
| { | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::lsp_array_state<other> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count, value); | ||||
|     detail::lsp_array_base& local = node->state().base(); | ||||
|     local.set(node); | ||||
|     result.release(); | ||||
|     return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start, | ||||
|         &local); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, | ||||
|     local_shared_ptr<T> >::type | ||||
| allocate_local_shared(const A& allocator, | ||||
|     const typename std::remove_extent<T>::type& value) | ||||
| { | ||||
|     enum { | ||||
|         count = std::extent<T>::value | ||||
|     }; | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::lsp_size_array_state<other, count> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count, value); | ||||
|     detail::lsp_array_base& local = node->state().base(); | ||||
|     local.set(node); | ||||
|     result.release(); | ||||
|     return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start, | ||||
|         &local); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, | ||||
|     local_shared_ptr<T> >::type | ||||
| allocate_local_shared_noinit(const A& allocator, std::size_t count) | ||||
| { | ||||
|     return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator), | ||||
|         count); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, | ||||
|     local_shared_ptr<T> >::type | ||||
| allocate_local_shared_noinit(const A& allocator) | ||||
| { | ||||
|     return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator)); | ||||
| } | ||||
|  | ||||
| } /* boost */ | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										346
									
								
								include/boost/smart_ptr/allocate_shared_array.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								include/boost/smart_ptr/allocate_shared_array.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,346 @@ | ||||
| /* | ||||
| Copyright 2012-2019 Glen Joseph Fernandes | ||||
| (glenjofe@gmail.com) | ||||
|  | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| (http://www.boost.org/LICENSE_1_0.txt) | ||||
| */ | ||||
| #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP | ||||
| #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP | ||||
|  | ||||
| #include <boost/core/allocator_access.hpp> | ||||
| #include <boost/core/alloc_construct.hpp> | ||||
| #include <boost/core/first_scalar.hpp> | ||||
| #include <boost/smart_ptr/shared_ptr.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_type_traits.hpp> | ||||
| #include <type_traits> | ||||
|  | ||||
| namespace boost { | ||||
| namespace detail { | ||||
|  | ||||
| template<class T> | ||||
| struct sp_array_element { | ||||
|     typedef typename std::remove_cv<typename | ||||
|         std::remove_extent<T>::type>::type type; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| struct sp_array_count { | ||||
|     enum { | ||||
|         value = 1 | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<class T, std::size_t N> | ||||
| struct sp_array_count<T[N]> { | ||||
|     enum { | ||||
|         value = N * sp_array_count<T>::value | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<std::size_t N, std::size_t M> | ||||
| struct sp_max_size { | ||||
|     enum { | ||||
|         value = N < M ? M : N | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<std::size_t N, std::size_t M> | ||||
| struct sp_align_up { | ||||
|     enum { | ||||
|         value = (N + M - 1) & ~(M - 1) | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| constexpr inline std::size_t | ||||
| sp_objects(std::size_t size) noexcept | ||||
| { | ||||
|     return (size + sizeof(T) - 1) / sizeof(T); | ||||
| } | ||||
|  | ||||
| template<class A> | ||||
| class sp_array_state { | ||||
| public: | ||||
|     typedef A type; | ||||
|  | ||||
|     template<class U> | ||||
|     sp_array_state(const U& _allocator, std::size_t _size) noexcept | ||||
|         : allocator_(_allocator), | ||||
|           size_(_size) { } | ||||
|  | ||||
|     A& allocator() noexcept { | ||||
|         return allocator_; | ||||
|     } | ||||
|  | ||||
|     std::size_t size() const noexcept { | ||||
|         return size_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     A allocator_; | ||||
|     std::size_t size_; | ||||
| }; | ||||
|  | ||||
| template<class A, std::size_t N> | ||||
| class sp_size_array_state { | ||||
| public: | ||||
|     typedef A type; | ||||
|  | ||||
|     template<class U> | ||||
|     sp_size_array_state(const U& _allocator, std::size_t) noexcept | ||||
|         : allocator_(_allocator) { } | ||||
|  | ||||
|     A& allocator() noexcept { | ||||
|         return allocator_; | ||||
|     } | ||||
|  | ||||
|     constexpr std::size_t size() const noexcept { | ||||
|         return N; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     A allocator_; | ||||
| }; | ||||
|  | ||||
| template<class T, class U> | ||||
| struct sp_array_alignment { | ||||
|     enum { | ||||
|         value = sp_max_size<std::alignment_of<T>::value, | ||||
|             std::alignment_of<U>::value>::value | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<class T, class U> | ||||
| struct sp_array_offset { | ||||
|     enum { | ||||
|         value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template<class U, class T> | ||||
| inline U* | ||||
| sp_array_start(T* base) noexcept | ||||
| { | ||||
|     enum { | ||||
|         size = sp_array_offset<T, U>::value | ||||
|     }; | ||||
|     return reinterpret_cast<U*>(reinterpret_cast<char*>(base) + size); | ||||
| } | ||||
|  | ||||
| template<class A, class T> | ||||
| class sp_array_creator { | ||||
|     typedef typename A::value_type element; | ||||
|  | ||||
|     enum { | ||||
|         offset = sp_array_offset<T, element>::value | ||||
|     }; | ||||
|  | ||||
|     typedef typename sp_type_with_alignment<sp_array_alignment<T, | ||||
|         element>::value>::type type; | ||||
|  | ||||
| public: | ||||
|     template<class U> | ||||
|     sp_array_creator(const U& other, std::size_t size) noexcept | ||||
|         : other_(other), | ||||
|           size_(sp_objects<type>(offset + sizeof(element) * size)) { } | ||||
|  | ||||
|     T* create() { | ||||
|         return reinterpret_cast<T*>(other_.allocate(size_)); | ||||
|     } | ||||
|  | ||||
|     void destroy(T* base) { | ||||
|         other_.deallocate(reinterpret_cast<type*>(base), size_); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     typename boost::allocator_rebind<A, type>::type other_; | ||||
|     std::size_t size_; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| class BOOST_SYMBOL_VISIBLE sp_array_base | ||||
|     : public sp_counted_base { | ||||
|     typedef typename T::type allocator; | ||||
|  | ||||
| public: | ||||
|     typedef typename allocator::value_type type; | ||||
|  | ||||
|     template<class A> | ||||
|     sp_array_base(const A& other, type* start, std::size_t size) | ||||
|         : state_(other, size) { | ||||
|         boost::alloc_construct_n(state_.allocator(), | ||||
|             boost::first_scalar(start), | ||||
|             state_.size() * sp_array_count<type>::value); | ||||
|     } | ||||
|  | ||||
|     template<class A, class U> | ||||
|     sp_array_base(const A& other, type* start, std::size_t size, const U& list) | ||||
|         : state_(other, size) { | ||||
|         enum { | ||||
|             count = sp_array_count<type>::value | ||||
|         }; | ||||
|         boost::alloc_construct_n(state_.allocator(), | ||||
|             boost::first_scalar(start), state_.size() * count, | ||||
|             boost::first_scalar(&list), count); | ||||
|     } | ||||
|  | ||||
|     T& state() noexcept { | ||||
|         return state_; | ||||
|     } | ||||
|  | ||||
|     void dispose() noexcept override { | ||||
|         boost::alloc_destroy_n(state_.allocator(), | ||||
|             boost::first_scalar(sp_array_start<type>(this)), | ||||
|             state_.size() * sp_array_count<type>::value); | ||||
|     } | ||||
|  | ||||
|     void destroy() noexcept override { | ||||
|         sp_array_creator<allocator, sp_array_base> other(state_.allocator(), | ||||
|             state_.size()); | ||||
|         this->~sp_array_base(); | ||||
|         other.destroy(this); | ||||
|     } | ||||
|  | ||||
|     void* get_deleter(const sp_typeinfo_&) noexcept override { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     void* get_local_deleter(const sp_typeinfo_&) | ||||
|         noexcept override { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     void* get_untyped_deleter() noexcept override { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     T state_; | ||||
| }; | ||||
|  | ||||
| template<class A, class T> | ||||
| struct sp_array_result { | ||||
| public: | ||||
|     template<class U> | ||||
|     sp_array_result(const U& other, std::size_t size) | ||||
|         : creator_(other, size), | ||||
|           result_(creator_.create()) { } | ||||
|  | ||||
|     ~sp_array_result() { | ||||
|         if (result_) { | ||||
|             creator_.destroy(result_); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     T* get() const noexcept { | ||||
|         return result_; | ||||
|     } | ||||
|  | ||||
|     void release() noexcept { | ||||
|         result_ = 0; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     sp_array_result(const sp_array_result&); | ||||
|     sp_array_result& operator=(const sp_array_result&); | ||||
|  | ||||
|     sp_array_creator<A, T> creator_; | ||||
|     T* result_; | ||||
| }; | ||||
|  | ||||
| } /* detail */ | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, shared_ptr<T> >::type | ||||
| allocate_shared(const A& allocator, std::size_t count) | ||||
| { | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::sp_array_state<other> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count); | ||||
|     result.release(); | ||||
|     return shared_ptr<T>(detail::sp_internal_constructor_tag(), start, | ||||
|         detail::shared_count(static_cast<detail::sp_counted_base*>(node))); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, shared_ptr<T> >::type | ||||
| allocate_shared(const A& allocator) | ||||
| { | ||||
|     enum { | ||||
|         count = std::extent<T>::value | ||||
|     }; | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::sp_size_array_state<other, std::extent<T>::value> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count); | ||||
|     result.release(); | ||||
|     return shared_ptr<T>(detail::sp_internal_constructor_tag(), start, | ||||
|         detail::shared_count(static_cast<detail::sp_counted_base*>(node))); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, shared_ptr<T> >::type | ||||
| allocate_shared(const A& allocator, std::size_t count, | ||||
|     const typename std::remove_extent<T>::type& value) | ||||
| { | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::sp_array_state<other> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count, value); | ||||
|     result.release(); | ||||
|     return shared_ptr<T>(detail::sp_internal_constructor_tag(), start, | ||||
|         detail::shared_count(static_cast<detail::sp_counted_base*>(node))); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, shared_ptr<T> >::type | ||||
| allocate_shared(const A& allocator, | ||||
|     const typename std::remove_extent<T>::type& value) | ||||
| { | ||||
|     enum { | ||||
|         count = std::extent<T>::value | ||||
|     }; | ||||
|     typedef typename detail::sp_array_element<T>::type element; | ||||
|     typedef typename allocator_rebind<A, element>::type other; | ||||
|     typedef detail::sp_size_array_state<other, std::extent<T>::value> state; | ||||
|     typedef detail::sp_array_base<state> base; | ||||
|     detail::sp_array_result<other, base> result(allocator, count); | ||||
|     base* node = result.get(); | ||||
|     element* start = detail::sp_array_start<element>(node); | ||||
|     ::new(static_cast<void*>(node)) base(allocator, start, count, value); | ||||
|     result.release(); | ||||
|     return shared_ptr<T>(detail::sp_internal_constructor_tag(), start, | ||||
|         detail::shared_count(static_cast<detail::sp_counted_base*>(node))); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, shared_ptr<T> >::type | ||||
| allocate_shared_noinit(const A& allocator, std::size_t count) | ||||
| { | ||||
|     return boost::allocate_shared<T>(boost::noinit_adapt(allocator), count); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, shared_ptr<T> >::type | ||||
| allocate_shared_noinit(const A& allocator) | ||||
| { | ||||
|     return boost::allocate_shared<T>(boost::noinit_adapt(allocator)); | ||||
| } | ||||
|  | ||||
| } /* boost */ | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										466
									
								
								include/boost/smart_ptr/allocate_unique.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								include/boost/smart_ptr/allocate_unique.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | ||||
| /* | ||||
| Copyright 2019-2021 Glen Joseph Fernandes | ||||
| (glenjofe@gmail.com) | ||||
|  | ||||
| Distributed under the Boost Software License, Version 1.0. | ||||
| (http://www.boost.org/LICENSE_1_0.txt) | ||||
| */ | ||||
| #ifndef BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP | ||||
| #define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP | ||||
|  | ||||
| #include <boost/core/allocator_access.hpp> | ||||
| #include <boost/core/alloc_construct.hpp> | ||||
| #include <boost/core/empty_value.hpp> | ||||
| #include <boost/core/first_scalar.hpp> | ||||
| #include <boost/core/noinit_adaptor.hpp> | ||||
| #include <boost/core/pointer_traits.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_type_traits.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <memory> | ||||
| #include <utility> | ||||
| #include <cstddef> | ||||
| #include <type_traits> | ||||
|  | ||||
| namespace boost { | ||||
| namespace detail { | ||||
|  | ||||
| template<class T> | ||||
| struct sp_alloc_size { | ||||
|     static constexpr std::size_t value = 1; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| struct sp_alloc_size<T[]> { | ||||
|     static constexpr std::size_t value = sp_alloc_size<T>::value; | ||||
| }; | ||||
|  | ||||
| template<class T, std::size_t N> | ||||
| struct sp_alloc_size<T[N]> { | ||||
|     static constexpr std::size_t value = N * sp_alloc_size<T>::value; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| struct sp_alloc_result { | ||||
|     typedef T type; | ||||
| }; | ||||
|  | ||||
| template<class T, std::size_t N> | ||||
| struct sp_alloc_result<T[N]> { | ||||
|     typedef T type[]; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| struct sp_alloc_value { | ||||
|     typedef typename std::remove_cv<typename | ||||
|         std::remove_extent<T>::type>::type type; | ||||
| }; | ||||
|  | ||||
| template<class T, class P> | ||||
| class sp_alloc_ptr { | ||||
| public: | ||||
|     typedef T element_type; | ||||
|  | ||||
|     sp_alloc_ptr() noexcept | ||||
|         : p_() { } | ||||
|  | ||||
| #if defined(BOOST_MSVC) && BOOST_MSVC == 1600 | ||||
|     sp_alloc_ptr(T* p) noexcept | ||||
|         : p_(const_cast<typename std::remove_cv<T>::type*>(p)) { } | ||||
| #endif | ||||
|  | ||||
|     sp_alloc_ptr(std::size_t, P p) noexcept | ||||
|         : p_(p) { } | ||||
|  | ||||
|     sp_alloc_ptr(std::nullptr_t) noexcept | ||||
|         : p_() { } | ||||
|  | ||||
|     T& operator*() const { | ||||
|         return *p_; | ||||
|     } | ||||
|  | ||||
|     T* operator->() const noexcept { | ||||
|         return boost::to_address(p_); | ||||
|     } | ||||
|  | ||||
|     explicit operator bool() const noexcept { | ||||
|         return !!p_; | ||||
|     } | ||||
|  | ||||
|     bool operator!() const noexcept { | ||||
|         return !p_; | ||||
|     } | ||||
|  | ||||
|     P ptr() const noexcept { | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     static constexpr std::size_t size() noexcept { | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_MSVC) && BOOST_MSVC < 1910 | ||||
|     static sp_alloc_ptr pointer_to(T& v) { | ||||
|         return sp_alloc_ptr(1, | ||||
|             std::pointer_traits<P>::pointer_to(const_cast<typename | ||||
|                 std::remove_cv<T>::type&>(v))); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| private: | ||||
|     P p_; | ||||
| }; | ||||
|  | ||||
| template<class T, class P> | ||||
| class sp_alloc_ptr<T[], P> { | ||||
| public: | ||||
|     typedef T element_type; | ||||
|  | ||||
|     sp_alloc_ptr() noexcept | ||||
|         : p_() { } | ||||
|  | ||||
|     sp_alloc_ptr(std::size_t n, P p) noexcept | ||||
|         : p_(p) | ||||
|         , n_(n) { } | ||||
|  | ||||
|     sp_alloc_ptr(std::nullptr_t) noexcept | ||||
|         : p_() { } | ||||
|  | ||||
|     T& operator[](std::size_t i) const { | ||||
|         return p_[i]; | ||||
|     } | ||||
|  | ||||
|     explicit operator bool() const noexcept { | ||||
|         return !!p_; | ||||
|     } | ||||
|  | ||||
|     bool operator!() const noexcept { | ||||
|         return !p_; | ||||
|     } | ||||
|  | ||||
|     P ptr() const noexcept { | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     std::size_t size() const noexcept { | ||||
|         return n_; | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_MSVC) && BOOST_MSVC < 1910 | ||||
|     static sp_alloc_ptr pointer_to(T& v) { | ||||
|         return sp_alloc_ptr(n_, | ||||
|             std::pointer_traits<P>::pointer_to(const_cast<typename | ||||
|                 std::remove_cv<T>::type&>(v))); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| private: | ||||
|     P p_; | ||||
|     std::size_t n_; | ||||
| }; | ||||
|  | ||||
| template<class T, std::size_t N, class P> | ||||
| class sp_alloc_ptr<T[N], P> { | ||||
| public: | ||||
|     typedef T element_type; | ||||
|  | ||||
|     sp_alloc_ptr() noexcept | ||||
|         : p_() { } | ||||
|  | ||||
|     sp_alloc_ptr(std::size_t, P p) noexcept | ||||
|         : p_(p) { } | ||||
|  | ||||
|     sp_alloc_ptr(std::nullptr_t) noexcept | ||||
|         : p_() { } | ||||
|  | ||||
|     T& operator[](std::size_t i) const { | ||||
|         return p_[i]; | ||||
|     } | ||||
|  | ||||
|     explicit operator bool() const noexcept { | ||||
|         return !!p_; | ||||
|     } | ||||
|  | ||||
|     bool operator!() const noexcept { | ||||
|         return !p_; | ||||
|     } | ||||
|  | ||||
|     P ptr() const noexcept { | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     static constexpr std::size_t size() noexcept { | ||||
|         return N; | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_MSVC) && BOOST_MSVC < 1910 | ||||
|     static sp_alloc_ptr pointer_to(T& v) { | ||||
|         return sp_alloc_ptr(N, | ||||
|             std::pointer_traits<P>::pointer_to(const_cast<typename | ||||
|                 std::remove_cv<T>::type&>(v))); | ||||
|     } | ||||
| #endif | ||||
|  | ||||
| private: | ||||
|     P p_; | ||||
| }; | ||||
|  | ||||
| template<class T, class P> | ||||
| inline bool | ||||
| operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs) | ||||
| { | ||||
|     return lhs.ptr() == rhs.ptr(); | ||||
| } | ||||
|  | ||||
| template<class T, class P> | ||||
| inline bool | ||||
| operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs) | ||||
| { | ||||
|     return !(lhs == rhs); | ||||
| } | ||||
|  | ||||
| template<class T, class P> | ||||
| inline bool | ||||
| operator==(const sp_alloc_ptr<T, P>& lhs, | ||||
|     std::nullptr_t) noexcept | ||||
| { | ||||
|     return !lhs.ptr(); | ||||
| } | ||||
|  | ||||
| template<class T, class P> | ||||
| inline bool | ||||
| operator==(std::nullptr_t, | ||||
|     const sp_alloc_ptr<T, P>& rhs) noexcept | ||||
| { | ||||
|     return !rhs.ptr(); | ||||
| } | ||||
|  | ||||
| template<class T, class P> | ||||
| inline bool | ||||
| operator!=(const sp_alloc_ptr<T, P>& lhs, | ||||
|     std::nullptr_t) noexcept | ||||
| { | ||||
|     return !!lhs.ptr(); | ||||
| } | ||||
|  | ||||
| template<class T, class P> | ||||
| inline bool | ||||
| operator!=(std::nullptr_t, | ||||
|     const sp_alloc_ptr<T, P>& rhs) noexcept | ||||
| { | ||||
|     return !!rhs.ptr(); | ||||
| } | ||||
|  | ||||
| template<class A> | ||||
| inline void | ||||
| sp_alloc_clear(A& a, typename boost::allocator_pointer<A>::type p, std::size_t, | ||||
|     std::false_type) | ||||
| { | ||||
|     boost::alloc_destroy(a, boost::to_address(p)); | ||||
| } | ||||
|  | ||||
| template<class A> | ||||
| inline void | ||||
| sp_alloc_clear(A& a, typename boost::allocator_pointer<A>::type p, | ||||
|     std::size_t n, std::true_type) | ||||
| { | ||||
| #if defined(BOOST_MSVC) && BOOST_MSVC < 1800 | ||||
|     if (!p) { | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|     boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)), | ||||
|         n * sp_alloc_size<typename A::value_type>::value); | ||||
| } | ||||
|  | ||||
| } /* detail */ | ||||
|  | ||||
| template<class T, class A> | ||||
| class alloc_deleter | ||||
|     : empty_value<typename allocator_rebind<A, | ||||
|         typename detail::sp_alloc_value<T>::type>::type> { | ||||
|     typedef typename allocator_rebind<A, | ||||
|         typename detail::sp_alloc_value<T>::type>::type allocator; | ||||
|     typedef empty_value<allocator> base; | ||||
|  | ||||
| public: | ||||
|     typedef detail::sp_alloc_ptr<T, | ||||
|         typename allocator_pointer<allocator>::type> pointer; | ||||
|  | ||||
|     explicit alloc_deleter(const allocator& a) noexcept | ||||
|         : base(empty_init_t(), a) { } | ||||
|  | ||||
|     void operator()(pointer p) { | ||||
|         detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), std::is_array<T>()); | ||||
|         base::get().deallocate(p.ptr(), p.size()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<class T, class A> | ||||
| using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >; | ||||
|  | ||||
| namespace detail { | ||||
|  | ||||
| template<class T, class A> | ||||
| class sp_alloc_make { | ||||
| public: | ||||
|     typedef typename boost::allocator_rebind<A, | ||||
|         typename sp_alloc_value<T>::type>::type allocator; | ||||
|  | ||||
| private: | ||||
|     typedef boost::alloc_deleter<T, A> deleter; | ||||
|  | ||||
| public: | ||||
|     typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type; | ||||
|  | ||||
|     sp_alloc_make(const A& a, std::size_t n) | ||||
|         : a_(a) | ||||
|         , n_(n) | ||||
|         , p_(a_.allocate(n)) { } | ||||
|  | ||||
|     ~sp_alloc_make() { | ||||
|         if (p_) { | ||||
|             a_.deallocate(p_, n_); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     typename allocator::value_type* get() const noexcept { | ||||
|         return boost::to_address(p_); | ||||
|     } | ||||
|  | ||||
|     allocator& state() noexcept { | ||||
|         return a_; | ||||
|     } | ||||
|  | ||||
|     type release() noexcept { | ||||
|         pointer p = p_; | ||||
|         p_ = pointer(); | ||||
|         return type(typename deleter::pointer(n_, p), deleter(a_)); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     typedef typename boost::allocator_pointer<allocator>::type pointer; | ||||
|  | ||||
|     allocator a_; | ||||
|     std::size_t n_; | ||||
|     pointer p_; | ||||
| }; | ||||
|  | ||||
| } /* detail */ | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<!std::is_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, 1); | ||||
|     boost::alloc_construct(c.state(), c.get()); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class A, class... Args> | ||||
| inline typename std::enable_if<!std::is_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc, Args&&... args) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, 1); | ||||
|     boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<!std::is_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc, typename detail::sp_type_identity<T>::type&& value) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, 1); | ||||
|     boost::alloc_construct(c.state(), c.get(), std::move(value)); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<!std::is_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type | ||||
| allocate_unique_noinit(const A& alloc) | ||||
| { | ||||
|     return boost::allocate_unique<T, noinit_adaptor<A> >(alloc); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc, std::size_t size) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, size); | ||||
|     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), | ||||
|         size * detail::sp_alloc_size<T>::value); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, | ||||
|     std::unique_ptr<typename detail::sp_alloc_result<T>::type, | ||||
|         alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, std::extent<T>::value); | ||||
|     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), | ||||
|         detail::sp_alloc_size<T>::value); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type | ||||
| allocate_unique_noinit(const A& alloc, std::size_t size) | ||||
| { | ||||
|     return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, | ||||
|     std::unique_ptr<typename detail::sp_alloc_result<T>::type, | ||||
|         alloc_deleter<T, noinit_adaptor<A> > > >::type | ||||
| allocate_unique_noinit(const A& alloc) | ||||
| { | ||||
|     return boost::allocate_unique<T, noinit_adaptor<A> >(alloc); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value, | ||||
|     std::unique_ptr<T, alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc, std::size_t size, | ||||
|     const typename std::remove_extent<T>::type& value) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, size); | ||||
|     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), | ||||
|         size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value), | ||||
|         detail::sp_alloc_size<typename std::remove_extent<T>::type>::value); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class A> | ||||
| inline typename std::enable_if<detail::sp_is_bounded_array<T>::value, | ||||
|     std::unique_ptr<typename detail::sp_alloc_result<T>::type, | ||||
|         alloc_deleter<T, A> > >::type | ||||
| allocate_unique(const A& alloc, | ||||
|     const typename std::remove_extent<T>::type& value) | ||||
| { | ||||
|     detail::sp_alloc_make<T, A> c(alloc, std::extent<T>::value); | ||||
|     boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()), | ||||
|         detail::sp_alloc_size<T>::value, boost::first_scalar(&value), | ||||
|         detail::sp_alloc_size<typename std::remove_extent<T>::type>::value); | ||||
|     return c.release(); | ||||
| } | ||||
|  | ||||
| template<class T, class U, class A> | ||||
| inline typename allocator_pointer<typename allocator_rebind<A, | ||||
|     typename detail::sp_alloc_value<T>::type>::type>::type | ||||
| get_allocator_pointer(const std::unique_ptr<T, | ||||
|     alloc_deleter<U, A> >& p) noexcept | ||||
| { | ||||
|     return p.get().ptr(); | ||||
| } | ||||
|  | ||||
| } /* boost */ | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										195
									
								
								include/boost/smart_ptr/atomic_shared_ptr.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								include/boost/smart_ptr/atomic_shared_ptr.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  atomic_shared_ptr.hpp | ||||
| // | ||||
| //  Copyright 2017 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/shared_ptr.hpp> | ||||
| #include <boost/smart_ptr/detail/spinlock.hpp> | ||||
| #include <cstring> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> class atomic_shared_ptr | ||||
| { | ||||
| private: | ||||
|  | ||||
|     boost::shared_ptr<T> p_; | ||||
|  | ||||
|     mutable boost::detail::spinlock l_; | ||||
|  | ||||
|     atomic_shared_ptr(const atomic_shared_ptr&); | ||||
|     atomic_shared_ptr& operator=(const atomic_shared_ptr&); | ||||
|  | ||||
| private: | ||||
|  | ||||
|     bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) noexcept | ||||
|     { | ||||
|         l_.lock(); | ||||
|  | ||||
|         if( p_._internal_equiv( v ) ) | ||||
|         { | ||||
|             p_.swap( w ); | ||||
|  | ||||
|             l_.unlock(); | ||||
|             return true; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             shared_ptr<T> tmp( p_ ); | ||||
|  | ||||
|             l_.unlock(); | ||||
|  | ||||
|             tmp.swap( v ); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| public: | ||||
|  | ||||
|     constexpr atomic_shared_ptr() noexcept: l_ BOOST_DETAIL_SPINLOCK_INIT | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     atomic_shared_ptr( shared_ptr<T> p ) noexcept | ||||
|         : p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept | ||||
|     { | ||||
|         boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|         p_.swap( r ); | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     constexpr bool is_lock_free() const noexcept | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     shared_ptr<T> load() const noexcept | ||||
|     { | ||||
|         boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     template<class M> shared_ptr<T> load( M ) const noexcept | ||||
|     { | ||||
|         boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     operator shared_ptr<T>() const noexcept | ||||
|     { | ||||
|         boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|         return p_; | ||||
|     } | ||||
|  | ||||
|     void store( shared_ptr<T> r ) noexcept | ||||
|     { | ||||
|         boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|         p_.swap( r ); | ||||
|     } | ||||
|  | ||||
|     template<class M> void store( shared_ptr<T> r, M ) noexcept | ||||
|     { | ||||
|         boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|         p_.swap( r ); | ||||
|     } | ||||
|  | ||||
|     shared_ptr<T> exchange( shared_ptr<T> r ) noexcept | ||||
|     { | ||||
|         { | ||||
|             boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|             p_.swap( r ); | ||||
|         } | ||||
|  | ||||
|         return std::move( r ); | ||||
|     } | ||||
|  | ||||
|     template<class M> shared_ptr<T> exchange( shared_ptr<T> r, M ) noexcept | ||||
|     { | ||||
|         { | ||||
|             boost::detail::spinlock::scoped_lock lock( l_ ); | ||||
|             p_.swap( r ); | ||||
|         } | ||||
|  | ||||
|         return std::move( r ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, w ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, w ); | ||||
|     } | ||||
|  | ||||
|     bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, w ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, w ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, w ); | ||||
|     } | ||||
|  | ||||
|     bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, w ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, std::move( w ) ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, std::move( w ) ); | ||||
|     } | ||||
|  | ||||
|     bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, std::move( w ) ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, std::move( w ) ); | ||||
|     } | ||||
|  | ||||
|     template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, std::move( w ) ); | ||||
|     } | ||||
|  | ||||
|     bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w ) noexcept | ||||
|     { | ||||
|         return compare_exchange( v, std::move( w ) ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED | ||||
							
								
								
									
										48
									
								
								include/boost/smart_ptr/bad_weak_ptr.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								include/boost/smart_ptr/bad_weak_ptr.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  boost/smart_ptr/bad_weak_ptr.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <exception> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| #if defined(BOOST_CLANG) | ||||
| // Intel C++ on Mac defines __clang__ but doesn't support the pragma | ||||
| # pragma clang diagnostic push | ||||
| # pragma clang diagnostic ignored "-Wweak-vtables" | ||||
| #endif | ||||
|  | ||||
| class bad_weak_ptr: public std::exception | ||||
| { | ||||
| public: | ||||
|  | ||||
|     char const * what() const noexcept override | ||||
|     { | ||||
|         return "tr1::bad_weak_ptr"; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #if defined(BOOST_CLANG) | ||||
| # pragma clang diagnostic pop | ||||
| #endif | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED | ||||
							
								
								
									
										104
									
								
								include/boost/smart_ptr/detail/atomic_count.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								include/boost/smart_ptr/detail/atomic_count.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count.hpp - thread/SMP safe reference counter | ||||
| // | ||||
| //  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright (c) 2013 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
| // | ||||
| //  typedef <implementation-defined> boost::detail::atomic_count; | ||||
| // | ||||
| //  atomic_count a(n); | ||||
| // | ||||
| //    (n is convertible to long) | ||||
| // | ||||
| //    Effects: Constructs an atomic_count with an initial value of n | ||||
| // | ||||
| //  a; | ||||
| // | ||||
| //    Returns: (long) the current value of a | ||||
| //    Memory Ordering: acquire | ||||
| // | ||||
| //  ++a; | ||||
| // | ||||
| //    Effects: Atomically increments the value of a | ||||
| //    Returns: (long) the new value of a | ||||
| //    Memory Ordering: acquire/release | ||||
| // | ||||
| //  --a; | ||||
| // | ||||
| //    Effects: Atomically decrements the value of a | ||||
| //    Returns: (long) the new value of a | ||||
| //    Memory Ordering: acquire/release | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp> | ||||
| #include <boost/smart_ptr/detail/deprecated_macros.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if defined( BOOST_AC_DISABLE_THREADS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_AC_USE_STD_ATOMIC ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp> | ||||
|  | ||||
| #elif defined( BOOST_AC_USE_SPINLOCK ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_spin.hpp> | ||||
|  | ||||
| #elif defined( BOOST_AC_USE_PTHREADS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_pt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_DISABLE_THREADS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_STD_ATOMIC ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_SPINLOCK ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_spin.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_PTHREADS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_pt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_HAS_GCC_INTRINSICS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp> | ||||
|  | ||||
| #elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_HAS_SYNC_INTRINSICS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_sync.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp> | ||||
|  | ||||
| #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) | ||||
| # include <boost/smart_ptr/detail/atomic_count_win32.hpp> | ||||
|  | ||||
| #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) | ||||
| # include <boost/smart_ptr/detail/atomic_count_gcc.hpp> | ||||
|  | ||||
| #elif !defined( BOOST_HAS_THREADS ) | ||||
| # include <boost/smart_ptr/detail/atomic_count_nt.hpp> | ||||
|  | ||||
| #else | ||||
| # include <boost/smart_ptr/detail/atomic_count_spin.hpp> | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED | ||||
| @@ -1,5 +1,5 @@ | ||||
| #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED | ||||
| 
 | ||||
| //
 | ||||
| //  boost/detail/atomic_count_gcc.hpp
 | ||||
| @@ -9,7 +9,7 @@ | ||||
| //  http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
 | ||||
| //
 | ||||
| //  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
 | ||||
| //  Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
 | ||||
| //  Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
 | ||||
| //  Copyright 2003-2005 Peter Dimov
 | ||||
| //
 | ||||
| //  Distributed under the Boost Software License, Version 1.0. (See
 | ||||
| @@ -17,12 +17,19 @@ | ||||
| //  http://www.boost.org/LICENSE_1_0.txt)
 | ||||
| //
 | ||||
| 
 | ||||
| #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) | ||||
| # include <ext/atomicity.h> | ||||
| #else | ||||
| #if __GNUC__ * 100 + __GNUC_MINOR__ >= 402 | ||||
| # include <ext/atomicity.h>  | ||||
| #else  | ||||
| # include <bits/atomicity.h> | ||||
| #endif | ||||
| 
 | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
| 
 | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using libstdc++ atomic_count") | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| namespace boost | ||||
| { | ||||
| 
 | ||||
| @@ -40,21 +47,21 @@ class atomic_count | ||||
| { | ||||
| public: | ||||
| 
 | ||||
|     explicit atomic_count(long v) : value_(v) {} | ||||
|     explicit atomic_count( long v ) : value_( v ) {} | ||||
| 
 | ||||
|     void operator++() | ||||
|     long operator++() | ||||
|     { | ||||
|         __atomic_add(&value_, 1); | ||||
|         return __exchange_and_add( &value_, +1 ) + 1; | ||||
|     } | ||||
| 
 | ||||
|     long operator--() | ||||
|     { | ||||
|         return __exchange_and_add(&value_, -1) - 1; | ||||
|         return __exchange_and_add( &value_, -1 ) - 1; | ||||
|     } | ||||
| 
 | ||||
|     operator long() const | ||||
|     { | ||||
|         return __exchange_and_add(&value_, 0); | ||||
|         return __exchange_and_add( &value_, 0 ); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
| @@ -69,4 +76,4 @@ private: | ||||
| 
 | ||||
| } // namespace boost
 | ||||
| 
 | ||||
| #endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
 | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
 | ||||
							
								
								
									
										63
									
								
								include/boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								include/boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED | ||||
|  | ||||
| // boost/detail/atomic_count_gcc_atomic.hpp | ||||
| // | ||||
| // atomic_count for g++ 4.7+ | ||||
| // | ||||
| // Copyright 2007, 2020 Peter Dimov | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #include <boost/cstdint.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using __atomic atomic_count") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class atomic_count | ||||
| { | ||||
| public: | ||||
|  | ||||
|     explicit atomic_count( long v ): value_( static_cast< boost::int_least32_t >( v ) ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     long operator++() | ||||
|     { | ||||
|         return __atomic_add_fetch( &value_, +1, __ATOMIC_ACQ_REL ); | ||||
|     } | ||||
|  | ||||
|     long operator--() | ||||
|     { | ||||
|         return __atomic_add_fetch( &value_, -1, __ATOMIC_ACQ_REL ); | ||||
|     } | ||||
|  | ||||
|     operator long() const | ||||
|     { | ||||
|         return __atomic_load_n( &value_, __ATOMIC_ACQUIRE ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     atomic_count(atomic_count const &); | ||||
|     atomic_count & operator=(atomic_count const &); | ||||
|  | ||||
|     boost::int_least32_t value_; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED | ||||
							
								
								
									
										88
									
								
								include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								include/boost/smart_ptr/detail/atomic_count_gcc_x86.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count_gcc_x86.hpp | ||||
| // | ||||
| //  atomic_count for g++ on 486+/AMD64 | ||||
| // | ||||
| //  Copyright 2007 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/detail/sp_obsolete.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using g++/x86 atomic_count") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| BOOST_SP_OBSOLETE() | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class atomic_count | ||||
| { | ||||
| public: | ||||
|  | ||||
|     explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {} | ||||
|  | ||||
|     long operator++() | ||||
|     { | ||||
|         return atomic_exchange_and_add( &value_, +1 ) + 1; | ||||
|     } | ||||
|  | ||||
|     long operator--() | ||||
|     { | ||||
|         return atomic_exchange_and_add( &value_, -1 ) - 1; | ||||
|     } | ||||
|  | ||||
|     operator long() const | ||||
|     { | ||||
|         return atomic_exchange_and_add( &value_, 0 ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     atomic_count(atomic_count const &); | ||||
|     atomic_count & operator=(atomic_count const &); | ||||
|  | ||||
|     mutable int value_; | ||||
|  | ||||
| private: | ||||
|  | ||||
|     static int atomic_exchange_and_add( int * pw, int dv ) | ||||
|     { | ||||
|         // int r = *pw; | ||||
|         // *pw += dv; | ||||
|         // return r; | ||||
|  | ||||
|         int r; | ||||
|  | ||||
|         __asm__ __volatile__ | ||||
|         ( | ||||
|             "lock\n\t" | ||||
|             "xadd %1, %0": | ||||
|             "+m"( *pw ), "=r"( r ): // outputs (%0, %1) | ||||
|             "1"( dv ): // inputs (%2 == %1) | ||||
|             "memory", "cc" // clobbers | ||||
|         ); | ||||
|  | ||||
|         return r; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED | ||||
							
								
								
									
										66
									
								
								include/boost/smart_ptr/detail/atomic_count_nt.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								include/boost/smart_ptr/detail/atomic_count_nt.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count_nt.hpp | ||||
| // | ||||
| //  Trivial atomic_count for the single-threaded case | ||||
| // | ||||
| //  http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html | ||||
| // | ||||
| //  Copyright 2013 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
| // | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using single-threaded, non-atomic atomic_count") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class atomic_count | ||||
| { | ||||
| public: | ||||
|  | ||||
|     explicit atomic_count( long v ): value_( v ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     long operator++() | ||||
|     { | ||||
|         return ++value_; | ||||
|     } | ||||
|  | ||||
|     long operator--() | ||||
|     { | ||||
|         return --value_; | ||||
|     } | ||||
|  | ||||
|     operator long() const | ||||
|     { | ||||
|         return value_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     atomic_count(atomic_count const &); | ||||
|     atomic_count & operator=(atomic_count const &); | ||||
|  | ||||
|     long value_; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_NT_HPP_INCLUDED | ||||
| @@ -1,5 +1,5 @@ | ||||
| #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED | ||||
| 
 | ||||
| //
 | ||||
| //  boost/detail/atomic_count_pthreads.hpp
 | ||||
| @@ -11,8 +11,16 @@ | ||||
| // http://www.boost.org/LICENSE_1_0.txt)
 | ||||
| //
 | ||||
| 
 | ||||
| #include <boost/assert.hpp> | ||||
| #include <pthread.h> | ||||
| 
 | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
| 
 | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using pthread_mutex atomic_count") | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| //
 | ||||
| //  The generic pthread_mutex-based implementation sometimes leads to
 | ||||
| //    inefficiencies. Example: a class with two atomic_count members
 | ||||
| @@ -37,12 +45,12 @@ private: | ||||
| 
 | ||||
|         scoped_lock(pthread_mutex_t & m): m_(m) | ||||
|         { | ||||
|             pthread_mutex_lock(&m_); | ||||
|             BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); | ||||
|         } | ||||
| 
 | ||||
|         ~scoped_lock() | ||||
|         { | ||||
|             pthread_mutex_unlock(&m_); | ||||
|             BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); | ||||
|         } | ||||
| 
 | ||||
|     private: | ||||
| @@ -54,18 +62,18 @@ public: | ||||
| 
 | ||||
|     explicit atomic_count(long v): value_(v) | ||||
|     { | ||||
|         pthread_mutex_init(&mutex_, 0); | ||||
|         BOOST_VERIFY( pthread_mutex_init( &mutex_, 0 ) == 0 ); | ||||
|     } | ||||
| 
 | ||||
|     ~atomic_count() | ||||
|     { | ||||
|         pthread_mutex_destroy(&mutex_); | ||||
|         BOOST_VERIFY( pthread_mutex_destroy( &mutex_ ) == 0 ); | ||||
|     } | ||||
| 
 | ||||
|     void operator++() | ||||
|     long operator++() | ||||
|     { | ||||
|         scoped_lock lock(mutex_); | ||||
|         ++value_; | ||||
|         return ++value_; | ||||
|     } | ||||
| 
 | ||||
|     long operator--() | ||||
| @@ -93,4 +101,4 @@ private: | ||||
| 
 | ||||
| } // namespace boost
 | ||||
| 
 | ||||
| #endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
 | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
 | ||||
							
								
								
									
										69
									
								
								include/boost/smart_ptr/detail/atomic_count_spin.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								include/boost/smart_ptr/detail/atomic_count_spin.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count_spin.hpp | ||||
| // | ||||
| //  Copyright (c) 2013 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/detail/spinlock_pool.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using spinlock-based atomic_count") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class atomic_count | ||||
| { | ||||
| private: | ||||
|  | ||||
| public: | ||||
|  | ||||
|     explicit atomic_count( long v ): value_( v ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     long operator++() | ||||
|     { | ||||
|         spinlock_pool<0>::scoped_lock lock( &value_ ); | ||||
|         return ++value_; | ||||
|     } | ||||
|  | ||||
|     long operator--() | ||||
|     { | ||||
|         spinlock_pool<0>::scoped_lock lock( &value_ ); | ||||
|         return --value_; | ||||
|     } | ||||
|  | ||||
|     operator long() const | ||||
|     { | ||||
|         spinlock_pool<0>::scoped_lock lock( &value_ ); | ||||
|         return value_; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     atomic_count(atomic_count const &); | ||||
|     atomic_count & operator=(atomic_count const &); | ||||
|  | ||||
|     long value_; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SPIN_HPP_INCLUDED | ||||
							
								
								
									
										67
									
								
								include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								include/boost/smart_ptr/detail/atomic_count_std_atomic.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count_std_atomic.hpp | ||||
| // | ||||
| //  atomic_count for std::atomic | ||||
| // | ||||
| //  Copyright 2013 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
| // | ||||
|  | ||||
| #include <atomic> | ||||
| #include <cstdint> | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using std::atomic atomic_count") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class atomic_count | ||||
| { | ||||
| public: | ||||
|  | ||||
|     explicit atomic_count( long v ): value_( static_cast< std::int_least32_t >( v ) ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     long operator++() | ||||
|     { | ||||
|         return value_.fetch_add( 1, std::memory_order_acq_rel ) + 1; | ||||
|     } | ||||
|  | ||||
|     long operator--() | ||||
|     { | ||||
|         return value_.fetch_sub( 1, std::memory_order_acq_rel ) - 1; | ||||
|     } | ||||
|  | ||||
|     operator long() const | ||||
|     { | ||||
|         return value_.load( std::memory_order_acquire ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     atomic_count(atomic_count const &); | ||||
|     atomic_count & operator=(atomic_count const &); | ||||
|  | ||||
|     std::atomic_int_least32_t value_; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_STD_ATOMIC_HPP_INCLUDED | ||||
							
								
								
									
										72
									
								
								include/boost/smart_ptr/detail/atomic_count_sync.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								include/boost/smart_ptr/detail/atomic_count_sync.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  boost/detail/atomic_count_sync.hpp | ||||
| // | ||||
| //  atomic_count for g++ 4.1+ | ||||
| // | ||||
| //  http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html | ||||
| // | ||||
| //  Copyright 2007 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
|  | ||||
| #include <boost/cstdint.hpp> | ||||
|  | ||||
| #if defined( __ia64__ ) && defined( __INTEL_COMPILER ) | ||||
| # include <ia64intrin.h> | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using __sync atomic_count") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class atomic_count | ||||
| { | ||||
| public: | ||||
|  | ||||
|     explicit atomic_count( long v ): value_( static_cast< boost::int_least32_t >( v ) ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     long operator++() | ||||
|     { | ||||
|         return __sync_add_and_fetch( &value_, 1 ); | ||||
|     } | ||||
|  | ||||
|     long operator--() | ||||
|     { | ||||
|         return __sync_add_and_fetch( &value_, -1 ); | ||||
|     } | ||||
|  | ||||
|     operator long() const | ||||
|     { | ||||
|         return __sync_fetch_and_add( &value_, 0 ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     atomic_count(atomic_count const &); | ||||
|     atomic_count & operator=(atomic_count const &); | ||||
|  | ||||
|     mutable boost::int_least32_t value_; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED | ||||
| @@ -1,5 +1,5 @@ | ||||
| #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED | ||||
| 
 | ||||
| // MS compatible compilers support #pragma once
 | ||||
| 
 | ||||
| @@ -17,7 +17,14 @@ | ||||
| // http://www.boost.org/LICENSE_1_0.txt)
 | ||||
| //
 | ||||
| 
 | ||||
| #include <boost/detail/interlocked.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_interlocked.hpp> | ||||
| 
 | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
| 
 | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using Win32 atomic_count") | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| namespace boost | ||||
| { | ||||
| @@ -35,12 +42,12 @@ public: | ||||
| 
 | ||||
|     long operator++() | ||||
|     { | ||||
|         return BOOST_INTERLOCKED_INCREMENT( &value_ ); | ||||
|         return BOOST_SP_INTERLOCKED_INCREMENT( &value_ ); | ||||
|     } | ||||
| 
 | ||||
|     long operator--() | ||||
|     { | ||||
|         return BOOST_INTERLOCKED_DECREMENT( &value_ ); | ||||
|         return BOOST_SP_INTERLOCKED_DECREMENT( &value_ ); | ||||
|     } | ||||
| 
 | ||||
|     operator long() const | ||||
| @@ -60,4 +67,4 @@ private: | ||||
| 
 | ||||
| } // namespace boost
 | ||||
| 
 | ||||
| #endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
 | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
 | ||||
							
								
								
									
										52
									
								
								include/boost/smart_ptr/detail/deprecated_macros.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								include/boost/smart_ptr/detail/deprecated_macros.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_DEPRECATED_MACROS_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_DEPRECATED_MACROS_HPP_INCLUDED | ||||
|  | ||||
| // Copyright 2024 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_ENABLE_DEBUG_HOOKS has been deprecated in 1.87 and support for it was removed in 1.90.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_STD_ALLOCATOR has been deprecated in 1.87 and support for it was removed in 1.90.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_QUICK_ALLOCATOR has been deprecated in 1.87 and support for it was removed in 1.90.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_AC_USE_SPINLOCK) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_AC_USE_SPINLOCK has been deprecated in 1.87 and support for it will be removed.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_AC_USE_PTHREADS) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_AC_USE_PTHREADS has been deprecated in 1.87 and support for it will be removed.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_SPINLOCK) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_SPINLOCK has been deprecated in 1.87 and support for it will be removed.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_PTHREADS) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_PTHREADS has been deprecated in 1.87 and support for it will be removed.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_DEPRECATED_MACROS_HPP_INCLUDED | ||||
							
								
								
									
										39
									
								
								include/boost/smart_ptr/detail/lightweight_mutex.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								include/boost/smart_ptr/detail/lightweight_mutex.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  boost/detail/lightweight_mutex.hpp - lightweight mutex | ||||
| // | ||||
| //  Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // 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) | ||||
| // | ||||
| //  typedef <unspecified> boost::detail::lightweight_mutex; | ||||
| // | ||||
| //  boost::detail::lightweight_mutex is a header-only implementation of | ||||
| //  a subset of the Mutex concept requirements: | ||||
| // | ||||
| //  http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex | ||||
| // | ||||
| //  It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX. | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if !defined(BOOST_NO_CXX11_HDR_MUTEX ) | ||||
| #  include <boost/smart_ptr/detail/lwm_std_mutex.hpp> | ||||
| #elif defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) | ||||
| #  include <boost/smart_ptr/detail/lwm_win32_cs.hpp> | ||||
| #else | ||||
| #  include <boost/smart_ptr/detail/lwm_pthreads.hpp> | ||||
| #endif | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED | ||||
							
								
								
									
										164
									
								
								include/boost/smart_ptr/detail/lightweight_thread.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								include/boost/smart_ptr/detail/lightweight_thread.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| //  boost/detail/lightweight_thread.hpp | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright (c) 2008, 2018 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
| // | ||||
| // | ||||
| //  typedef /*...*/ lw_thread_t; // as pthread_t | ||||
| //  template<class F> int lw_thread_create( lw_thread_t & th, F f ); | ||||
| //  void lw_thread_join( lw_thread_t th ); | ||||
|  | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <memory> | ||||
| #include <cerrno> | ||||
|  | ||||
| #if defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
| #include <pthread.h> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| typedef ::pthread_t lw_thread_t; | ||||
|  | ||||
| inline int lw_thread_create_( lw_thread_t* thread, const pthread_attr_t* attr, void* (*start_routine)( void* ), void* arg ) | ||||
| { | ||||
|     return ::pthread_create( thread, attr, start_routine, arg ); | ||||
| } | ||||
|  | ||||
| inline void lw_thread_join( lw_thread_t th ) | ||||
| { | ||||
|     ::pthread_join( th, 0 ); | ||||
| } | ||||
|  | ||||
| } // namespace detail | ||||
| } // namespace boost | ||||
|  | ||||
| #else // defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
| #include <windows.h> | ||||
| #include <process.h> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| typedef HANDLE lw_thread_t; | ||||
|  | ||||
| inline int lw_thread_create_( lw_thread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg ) | ||||
| { | ||||
|     HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); | ||||
|  | ||||
|     if( h != 0 ) | ||||
|     { | ||||
|         *thread = h; | ||||
|         return 0; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return EAGAIN; | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline void lw_thread_join( lw_thread_t thread ) | ||||
| { | ||||
|     ::WaitForSingleObject( thread, INFINITE ); | ||||
|     ::CloseHandle( thread ); | ||||
| } | ||||
|  | ||||
| } // namespace detail | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class lw_abstract_thread | ||||
| { | ||||
| public: | ||||
|  | ||||
|     virtual ~lw_abstract_thread() {} | ||||
|     virtual void run() = 0; | ||||
| }; | ||||
|  | ||||
| #if defined( BOOST_HAS_PTHREADS ) | ||||
|  | ||||
| extern "C" inline void * lw_thread_routine( void * pv ) | ||||
| { | ||||
|     std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) ); | ||||
|  | ||||
|     pt->run(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| inline unsigned __stdcall lw_thread_routine( void * pv ) | ||||
| { | ||||
|     std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) ); | ||||
|  | ||||
|     pt->run(); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| template<class F> class lw_thread_impl: public lw_abstract_thread | ||||
| { | ||||
| public: | ||||
|  | ||||
|     explicit lw_thread_impl( F f ): f_( f ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void run() | ||||
|     { | ||||
|         f_(); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     F f_; | ||||
| }; | ||||
|  | ||||
| template<class F> int lw_thread_create( lw_thread_t & th, F f ) | ||||
| { | ||||
|     std::unique_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) ); | ||||
|  | ||||
|     int r = lw_thread_create_( &th, 0, lw_thread_routine, p.get() ); | ||||
|  | ||||
|     if( r == 0 ) | ||||
|     { | ||||
|         p.release(); | ||||
|     } | ||||
|  | ||||
|     return r; | ||||
| } | ||||
|  | ||||
| } // namespace detail | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_THREAD_HPP_INCLUDED | ||||
							
								
								
									
										144
									
								
								include/boost/smart_ptr/detail/local_counted_base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								include/boost/smart_ptr/detail/local_counted_base.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| //  detail/local_counted_base.hpp | ||||
| // | ||||
| //  Copyright 2017 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
|  | ||||
| #include <boost/smart_ptr/detail/shared_count.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <utility> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class BOOST_SYMBOL_VISIBLE local_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     local_counted_base & operator= ( local_counted_base const & ); | ||||
|  | ||||
| private: | ||||
|  | ||||
|     // not 'int' or 'unsigned' to avoid aliasing and enable optimizations | ||||
|     enum count_type { min_ = 0, initial_ = 1, max_ = 2147483647 }; | ||||
|  | ||||
|     count_type local_use_count_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     constexpr local_counted_base() noexcept: local_use_count_( initial_ ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     constexpr local_counted_base( local_counted_base const & ) noexcept: local_use_count_( initial_ ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     virtual ~local_counted_base() /*noexcept*/ | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     virtual void local_cb_destroy() noexcept = 0; | ||||
|  | ||||
|     virtual boost::detail::shared_count local_cb_get_shared_count() const noexcept = 0; | ||||
|  | ||||
|     void add_ref() noexcept | ||||
|     { | ||||
| #if !defined(__NVCC__) | ||||
| #if defined( __has_builtin ) | ||||
| # if __has_builtin( __builtin_assume ) | ||||
|  | ||||
|         __builtin_assume( local_use_count_ >= 1 ); | ||||
|  | ||||
| # endif | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|         local_use_count_ = static_cast<count_type>( local_use_count_ + 1 ); | ||||
|     } | ||||
|  | ||||
|     void release() noexcept | ||||
|     { | ||||
|         local_use_count_ = static_cast<count_type>( local_use_count_ - 1 ); | ||||
|  | ||||
|         if( local_use_count_ == 0 ) | ||||
|         { | ||||
|             local_cb_destroy(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     long local_use_count() const noexcept | ||||
|     { | ||||
|         return local_use_count_; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class BOOST_SYMBOL_VISIBLE local_counted_impl: public local_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     local_counted_impl( local_counted_impl const & ); | ||||
|  | ||||
| private: | ||||
|  | ||||
|     shared_count pn_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     explicit local_counted_impl( shared_count const& pn ) noexcept: pn_( pn ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     explicit local_counted_impl( shared_count && pn ) noexcept: pn_( std::move(pn) ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void local_cb_destroy() noexcept override | ||||
|     { | ||||
|         delete this; | ||||
|     } | ||||
|  | ||||
|     boost::detail::shared_count local_cb_get_shared_count() const noexcept override | ||||
|     { | ||||
|         return pn_; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class BOOST_SYMBOL_VISIBLE local_counted_impl_em: public local_counted_base | ||||
| { | ||||
| public: | ||||
|  | ||||
|     shared_count pn_; | ||||
|  | ||||
|     void local_cb_destroy() noexcept override | ||||
|     { | ||||
|         shared_count().swap( pn_ ); | ||||
|     } | ||||
|  | ||||
|     boost::detail::shared_count local_cb_get_shared_count() const noexcept override | ||||
|     { | ||||
|         return pn_; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED | ||||
							
								
								
									
										83
									
								
								include/boost/smart_ptr/detail/local_sp_deleter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								include/boost/smart_ptr/detail/local_sp_deleter.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| //  detail/local_sp_deleter.hpp | ||||
| // | ||||
| //  Copyright 2017 Peter Dimov | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| //  See http://www.boost.org/libs/smart_ptr/ for documentation. | ||||
|  | ||||
| #include <boost/smart_ptr/detail/local_counted_base.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<class D> class local_sp_deleter: public local_counted_impl_em | ||||
| { | ||||
| private: | ||||
|  | ||||
|     D d_; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     local_sp_deleter(): d_() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     explicit local_sp_deleter( D const& d ) noexcept: d_( d ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     explicit local_sp_deleter( D&& d ) noexcept: d_( std::move(d) ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     D& deleter() noexcept | ||||
|     { | ||||
|         return d_; | ||||
|     } | ||||
|  | ||||
|     template<class Y> void operator()( Y* p ) noexcept | ||||
|     { | ||||
|         d_( p ); | ||||
|     } | ||||
|  | ||||
|     void operator()( std::nullptr_t p ) noexcept | ||||
|     { | ||||
|         d_( p ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template<> class local_sp_deleter<void> | ||||
| { | ||||
| }; | ||||
|  | ||||
| template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) noexcept | ||||
| { | ||||
|     return &p->deleter(); | ||||
| } | ||||
|  | ||||
| inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) noexcept | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED | ||||
| @@ -1,5 +1,5 @@ | ||||
| #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED | ||||
| 
 | ||||
| // MS compatible compilers support #pragma once
 | ||||
| 
 | ||||
| @@ -17,6 +17,7 @@ | ||||
| // http://www.boost.org/LICENSE_1_0.txt)
 | ||||
| //
 | ||||
| 
 | ||||
| #include <boost/assert.hpp> | ||||
| #include <pthread.h> | ||||
| 
 | ||||
| namespace boost | ||||
| @@ -42,15 +43,15 @@ public: | ||||
| // HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
 | ||||
| 
 | ||||
| #if defined(__hpux) && defined(_DECTHREADS_) | ||||
|         pthread_mutex_init(&m_, pthread_mutexattr_default); | ||||
|         BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 ); | ||||
| #else | ||||
|         pthread_mutex_init(&m_, 0); | ||||
|         BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 ); | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
|     ~lightweight_mutex() | ||||
|     { | ||||
|         pthread_mutex_destroy(&m_); | ||||
|         BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 ); | ||||
|     } | ||||
| 
 | ||||
|     class scoped_lock; | ||||
| @@ -69,12 +70,12 @@ public: | ||||
| 
 | ||||
|         scoped_lock(lightweight_mutex & m): m_(m.m_) | ||||
|         { | ||||
|             pthread_mutex_lock(&m_); | ||||
|             BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); | ||||
|         } | ||||
| 
 | ||||
|         ~scoped_lock() | ||||
|         { | ||||
|             pthread_mutex_unlock(&m_); | ||||
|             BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); | ||||
|         } | ||||
|     }; | ||||
| }; | ||||
| @@ -83,4 +84,4 @@ public: | ||||
| 
 | ||||
| } // namespace boost
 | ||||
| 
 | ||||
| #endif // #ifndef BOOST_DETAIL_LWM_PTHREADS_HPP_INCLUDED
 | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
 | ||||
							
								
								
									
										62
									
								
								include/boost/smart_ptr/detail/lwm_std_mutex.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								include/boost/smart_ptr/detail/lwm_std_mutex.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED | ||||
|  | ||||
| // Copyright 2020 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <mutex> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| class lightweight_mutex | ||||
| { | ||||
| private: | ||||
|  | ||||
|     std::mutex m_; | ||||
|  | ||||
|     lightweight_mutex(lightweight_mutex const &); | ||||
|     lightweight_mutex & operator=(lightweight_mutex const &); | ||||
|  | ||||
| public: | ||||
|  | ||||
|     lightweight_mutex() | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     class scoped_lock; | ||||
|     friend class scoped_lock; | ||||
|  | ||||
|     class scoped_lock | ||||
|     { | ||||
|     private: | ||||
|  | ||||
|         std::mutex & m_; | ||||
|  | ||||
|         scoped_lock(scoped_lock const &); | ||||
|         scoped_lock & operator=(scoped_lock const &); | ||||
|  | ||||
|     public: | ||||
|  | ||||
|         scoped_lock( lightweight_mutex & m ): m_( m.m_ ) | ||||
|         { | ||||
|             m_.lock(); | ||||
|         } | ||||
|  | ||||
|         ~scoped_lock() | ||||
|         { | ||||
|             m_.unlock(); | ||||
|         } | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED | ||||
| @@ -1,5 +1,5 @@ | ||||
| #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED | ||||
| 
 | ||||
| // MS compatible compilers support #pragma once
 | ||||
| 
 | ||||
| @@ -18,7 +18,13 @@ | ||||
| //
 | ||||
| 
 | ||||
| #ifdef BOOST_USE_WINDOWS_H | ||||
| #  include <windows.h> | ||||
| 
 | ||||
| #include <windows.h> | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| struct _RTL_CRITICAL_SECTION; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| namespace boost | ||||
| @@ -29,7 +35,7 @@ namespace detail | ||||
| 
 | ||||
| #ifndef BOOST_USE_WINDOWS_H | ||||
| 
 | ||||
| struct CRITICAL_SECTION | ||||
| struct critical_section | ||||
| { | ||||
|     struct critical_section_debug * DebugInfo; | ||||
|     long LockCount; | ||||
| @@ -43,10 +49,23 @@ struct CRITICAL_SECTION | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *); | ||||
| extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *); | ||||
| 
 | ||||
| typedef ::_RTL_CRITICAL_SECTION rtl_critical_section; | ||||
| 
 | ||||
| #else // #ifndef BOOST_USE_WINDOWS_H
 | ||||
| 
 | ||||
| typedef ::CRITICAL_SECTION critical_section; | ||||
| 
 | ||||
| using ::InitializeCriticalSection; | ||||
| using ::EnterCriticalSection; | ||||
| using ::LeaveCriticalSection; | ||||
| using ::DeleteCriticalSection; | ||||
| 
 | ||||
| typedef ::CRITICAL_SECTION rtl_critical_section; | ||||
| 
 | ||||
| #endif // #ifndef BOOST_USE_WINDOWS_H
 | ||||
| 
 | ||||
| @@ -54,7 +73,7 @@ class lightweight_mutex | ||||
| { | ||||
| private: | ||||
| 
 | ||||
|     CRITICAL_SECTION cs_; | ||||
|     critical_section cs_; | ||||
| 
 | ||||
|     lightweight_mutex(lightweight_mutex const &); | ||||
|     lightweight_mutex & operator=(lightweight_mutex const &); | ||||
| @@ -63,12 +82,12 @@ public: | ||||
| 
 | ||||
|     lightweight_mutex() | ||||
|     { | ||||
|         InitializeCriticalSection(&cs_); | ||||
|         boost::detail::InitializeCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_)); | ||||
|     } | ||||
| 
 | ||||
|     ~lightweight_mutex() | ||||
|     { | ||||
|         DeleteCriticalSection(&cs_); | ||||
|         boost::detail::DeleteCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_)); | ||||
|     } | ||||
| 
 | ||||
|     class scoped_lock; | ||||
| @@ -87,12 +106,12 @@ public: | ||||
| 
 | ||||
|         explicit scoped_lock(lightweight_mutex & m): m_(m) | ||||
|         { | ||||
|             EnterCriticalSection(&m_.cs_); | ||||
|             boost::detail::EnterCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_)); | ||||
|         } | ||||
| 
 | ||||
|         ~scoped_lock() | ||||
|         { | ||||
|             LeaveCriticalSection(&m_.cs_); | ||||
|             boost::detail::LeaveCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_)); | ||||
|         } | ||||
|     }; | ||||
| }; | ||||
| @@ -101,4 +120,4 @@ public: | ||||
| 
 | ||||
| } // namespace boost
 | ||||
| 
 | ||||
| #endif // #ifndef BOOST_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
 | ||||
| #endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
 | ||||
							
								
								
									
										63
									
								
								include/boost/smart_ptr/detail/quick_allocator.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								include/boost/smart_ptr/detail/quick_allocator.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
|  | ||||
| // Copyright 2003 David Abrahams | ||||
| // Copyright 2003, 2025 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #include <boost/config/header_deprecated.hpp> | ||||
| #include <memory> | ||||
| #include <cstddef> | ||||
|  | ||||
| BOOST_HEADER_DEPRECATED("std::allocator or std::pmr::synchronized_pool_resource") | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<class T> struct quick_allocator | ||||
| { | ||||
|     static void* alloc() | ||||
|     { | ||||
|         return std::allocator<T>().allocate( 1 ); | ||||
|     } | ||||
|  | ||||
|     static void* alloc( std::size_t n ) | ||||
|     { | ||||
|         if( n != sizeof(T) ) // class-specific delete called for a derived object | ||||
|         { | ||||
|             return ::operator new( n ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return alloc(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void dealloc( void* p ) | ||||
|     { | ||||
|         if( p != 0 ) // 18.4.1.1/13 | ||||
|         { | ||||
|             std::allocator<T>().deallocate( static_cast<T*>( p ), 1 ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void dealloc( void* p, std::size_t n ) | ||||
|     { | ||||
|         if( n != sizeof(T) ) // class-specific delete called for a derived object | ||||
|         { | ||||
|             ::operator delete( p ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             dealloc( p ); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
							
								
								
									
										581
									
								
								include/boost/smart_ptr/detail/shared_count.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										581
									
								
								include/boost/smart_ptr/detail/shared_count.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,581 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/shared_count.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright 2004-2005 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/bad_weak_ptr.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_counted_base.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_counted_impl.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp> | ||||
| #include <boost/smart_ptr/detail/deprecated_macros.hpp> | ||||
| #include <boost/core/checked_delete.hpp> | ||||
| #include <boost/throw_exception.hpp> | ||||
| #include <boost/core/addressof.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <boost/config/workaround.hpp> | ||||
| #include <boost/cstdint.hpp> | ||||
| #include <memory>            // std::auto_ptr | ||||
| #include <functional>        // std::less | ||||
| #include <cstddef>           // std::size_t | ||||
|  | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
| # include <new>              // std::bad_alloc | ||||
| #endif | ||||
|  | ||||
| #if defined( BOOST_SP_DISABLE_DEPRECATED ) | ||||
| #pragma GCC diagnostic push | ||||
| #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace movelib | ||||
| { | ||||
|  | ||||
| template< class T, class D > class unique_ptr; | ||||
|  | ||||
| } // namespace movelib | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| struct sp_nothrow_tag {}; | ||||
|  | ||||
| template< class D > struct sp_inplace_tag | ||||
| { | ||||
| }; | ||||
|  | ||||
| template< class T > class sp_reference_wrapper | ||||
| {  | ||||
| public: | ||||
|  | ||||
|     explicit sp_reference_wrapper( T & t): t_( boost::addressof( t ) ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template< class Y > void operator()( Y * p ) const | ||||
|     { | ||||
|         (*t_)( p ); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|  | ||||
|     T * t_; | ||||
| }; | ||||
|  | ||||
| template< class D > struct sp_convert_reference | ||||
| { | ||||
|     typedef D type; | ||||
| }; | ||||
|  | ||||
| template< class D > struct sp_convert_reference< D& > | ||||
| { | ||||
|     typedef sp_reference_wrapper< D > type; | ||||
| }; | ||||
|  | ||||
| template<class T> std::size_t sp_hash_pointer( T* p ) noexcept | ||||
| { | ||||
|     boost::uintptr_t v = reinterpret_cast<boost::uintptr_t>( p ); | ||||
|  | ||||
|     // match boost::hash<T*> | ||||
|     return static_cast<std::size_t>( v + ( v >> 3 ) ); | ||||
| } | ||||
|  | ||||
| class weak_count; | ||||
|  | ||||
| class shared_count | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base * pi_; | ||||
|  | ||||
|     friend class weak_count; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     constexpr shared_count() noexcept: pi_(0) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     constexpr explicit shared_count( sp_counted_base * pi ) noexcept: pi_( pi ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> explicit shared_count( Y * p ): pi_( 0 ) | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = new sp_counted_impl_p<Y>( p ); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             boost::checked_delete( p ); | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = new sp_counted_impl_p<Y>( p ); | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             boost::checked_delete( p ); | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     template<class P, class D> shared_count( P p, D d ): pi_(0) | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = new sp_counted_impl_pd<P, D>(p, d); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             d(p); // delete p | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = new sp_counted_impl_pd<P, D>(p, d); | ||||
|  | ||||
|         if(pi_ == 0) | ||||
|         { | ||||
|             d(p); // delete p | ||||
|             boost::throw_exception(std::bad_alloc()); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 ) | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = new sp_counted_impl_pd< P, D >( p ); | ||||
|         } | ||||
|         catch( ... ) | ||||
|         { | ||||
|             D::operator_fn( p ); // delete p | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = new sp_counted_impl_pd< P, D >( p ); | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             D::operator_fn( p ); // delete p | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif // #ifndef BOOST_NO_EXCEPTIONS | ||||
|     } | ||||
|  | ||||
|     template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 ) | ||||
|     { | ||||
|         typedef sp_counted_impl_pda<P, D, A> impl_type; | ||||
|  | ||||
|         typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2; | ||||
|  | ||||
|         A2 a2( a ); | ||||
|  | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = a2.allocate( 1 ); | ||||
|             ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             d( p ); | ||||
|  | ||||
|             if( pi_ != 0 ) | ||||
|             { | ||||
|                 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); | ||||
|             } | ||||
|  | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = a2.allocate( 1 ); | ||||
|  | ||||
|         if( pi_ != 0 ) | ||||
|         { | ||||
|             ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             d( p ); | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 ) | ||||
|     { | ||||
|         typedef sp_counted_impl_pda< P, D, A > impl_type; | ||||
|  | ||||
|         typedef typename std::allocator_traits<A>::template rebind_alloc< impl_type > A2; | ||||
|  | ||||
|         A2 a2( a ); | ||||
|  | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         try | ||||
|         { | ||||
|             pi_ = a2.allocate( 1 ); | ||||
|             ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); | ||||
|         } | ||||
|         catch(...) | ||||
|         { | ||||
|             D::operator_fn( p ); | ||||
|  | ||||
|             if( pi_ != 0 ) | ||||
|             { | ||||
|                 a2.deallocate( static_cast< impl_type* >( pi_ ), 1 ); | ||||
|             } | ||||
|  | ||||
|             throw; | ||||
|         } | ||||
|  | ||||
| #else | ||||
|  | ||||
|         pi_ = a2.allocate( 1 ); | ||||
|  | ||||
|         if( pi_ != 0 ) | ||||
|         { | ||||
|             ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             D::operator_fn( p ); | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif // #ifndef BOOST_NO_EXCEPTIONS | ||||
|     } | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     // auto_ptr<Y> is special cased to provide the strong guarantee | ||||
|  | ||||
|     template<class Y> | ||||
|     explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) ) | ||||
|     { | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             boost::throw_exception(std::bad_alloc()); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|         r.release(); | ||||
|     } | ||||
|  | ||||
| #endif  | ||||
|  | ||||
|     template<class Y, class D> | ||||
|     explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 ) | ||||
|     { | ||||
|         typedef typename sp_convert_reference<D>::type D2; | ||||
|  | ||||
|         D2 d2( static_cast<D&&>( r.get_deleter() ) ); | ||||
|         pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 ); | ||||
|  | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|         r.release(); | ||||
|     } | ||||
|  | ||||
|     template<class Y, class D> | ||||
|     explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 ) | ||||
|     { | ||||
|         typedef typename sp_convert_reference<D>::type D2; | ||||
|  | ||||
|         D2 d2( r.get_deleter() ); | ||||
|         pi_ = new sp_counted_impl_pd< typename boost::movelib::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 ); | ||||
|  | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
|         if( pi_ == 0 ) | ||||
|         { | ||||
|             boost::throw_exception( std::bad_alloc() ); | ||||
|         } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|         r.release(); | ||||
|     } | ||||
|  | ||||
|     ~shared_count() /*noexcept*/ | ||||
|     { | ||||
|         if( pi_ != 0 ) pi_->release(); | ||||
|     } | ||||
|  | ||||
|     shared_count(shared_count const & r) noexcept: pi_(r.pi_) | ||||
|     { | ||||
|         if( pi_ != 0 ) pi_->add_ref_copy(); | ||||
|     } | ||||
|  | ||||
|     shared_count(shared_count && r) noexcept: pi_(r.pi_) | ||||
|     { | ||||
|         r.pi_ = 0; | ||||
|     } | ||||
|  | ||||
|     explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 | ||||
|     shared_count( weak_count const & r, sp_nothrow_tag ) noexcept; // constructs an empty *this when r.use_count() == 0 | ||||
|  | ||||
|     shared_count & operator= (shared_count const & r) noexcept | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|  | ||||
|         if( tmp != pi_ ) | ||||
|         { | ||||
|             if( tmp != 0 ) tmp->add_ref_copy(); | ||||
|             if( pi_ != 0 ) pi_->release(); | ||||
|             pi_ = tmp; | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     void swap(shared_count & r) noexcept | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|         r.pi_ = pi_; | ||||
|         pi_ = tmp; | ||||
|     } | ||||
|  | ||||
|     long use_count() const noexcept | ||||
|     { | ||||
|         return pi_ != 0? pi_->use_count(): 0; | ||||
|     } | ||||
|  | ||||
|     bool unique() const noexcept | ||||
|     { | ||||
|         return use_count() == 1; | ||||
|     } | ||||
|  | ||||
|     bool empty() const noexcept | ||||
|     { | ||||
|         return pi_ == 0; | ||||
|     } | ||||
|  | ||||
|     bool operator==( shared_count const & r ) const noexcept | ||||
|     { | ||||
|         return pi_ == r.pi_; | ||||
|     } | ||||
|  | ||||
|     bool operator==( weak_count const & r ) const noexcept; | ||||
|  | ||||
|     bool operator<( shared_count const & r ) const noexcept | ||||
|     { | ||||
|         return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||
|     } | ||||
|  | ||||
|     bool operator<( weak_count const & r ) const noexcept; | ||||
|  | ||||
|     void * get_deleter( sp_typeinfo_ const & ti ) const noexcept | ||||
|     { | ||||
|         return pi_? pi_->get_deleter( ti ): 0; | ||||
|     } | ||||
|  | ||||
|     void * get_local_deleter( sp_typeinfo_ const & ti ) const noexcept | ||||
|     { | ||||
|         return pi_? pi_->get_local_deleter( ti ): 0; | ||||
|     } | ||||
|  | ||||
|     void * get_untyped_deleter() const noexcept | ||||
|     { | ||||
|         return pi_? pi_->get_untyped_deleter(): 0; | ||||
|     } | ||||
|  | ||||
|     std::size_t hash_value() const noexcept | ||||
|     { | ||||
|         return sp_hash_pointer( pi_ ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class weak_count | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base * pi_; | ||||
|  | ||||
|     friend class shared_count; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     constexpr weak_count() noexcept: pi_(0) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     weak_count(shared_count const & r) noexcept: pi_(r.pi_) | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_add_ref(); | ||||
|     } | ||||
|  | ||||
|     weak_count(weak_count const & r) noexcept: pi_(r.pi_) | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_add_ref(); | ||||
|     } | ||||
|  | ||||
| // Move support | ||||
|  | ||||
|     weak_count(weak_count && r) noexcept: pi_(r.pi_) | ||||
|     { | ||||
|         r.pi_ = 0; | ||||
|     } | ||||
|  | ||||
|     ~weak_count() /*noexcept*/ | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_release(); | ||||
|     } | ||||
|  | ||||
|     weak_count & operator= (shared_count const & r) noexcept | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|  | ||||
|         if( tmp != pi_ ) | ||||
|         { | ||||
|             if(tmp != 0) tmp->weak_add_ref(); | ||||
|             if(pi_ != 0) pi_->weak_release(); | ||||
|             pi_ = tmp; | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     weak_count & operator= (weak_count const & r) noexcept | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|  | ||||
|         if( tmp != pi_ ) | ||||
|         { | ||||
|             if(tmp != 0) tmp->weak_add_ref(); | ||||
|             if(pi_ != 0) pi_->weak_release(); | ||||
|             pi_ = tmp; | ||||
|         } | ||||
|  | ||||
|         return *this; | ||||
|     } | ||||
|  | ||||
|     void swap(weak_count & r) noexcept | ||||
|     { | ||||
|         sp_counted_base * tmp = r.pi_; | ||||
|         r.pi_ = pi_; | ||||
|         pi_ = tmp; | ||||
|     } | ||||
|  | ||||
|     long use_count() const noexcept | ||||
|     { | ||||
|         return pi_ != 0? pi_->use_count(): 0; | ||||
|     } | ||||
|  | ||||
|     bool empty() const noexcept | ||||
|     { | ||||
|         return pi_ == 0; | ||||
|     } | ||||
|  | ||||
|     bool operator==( weak_count const & r ) const noexcept | ||||
|     { | ||||
|         return pi_ == r.pi_; | ||||
|     } | ||||
|  | ||||
|     bool operator==( shared_count const & r ) const noexcept | ||||
|     { | ||||
|         return pi_ == r.pi_; | ||||
|     } | ||||
|  | ||||
|     bool operator<( weak_count const & r ) const noexcept | ||||
|     { | ||||
|         return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||
|     } | ||||
|  | ||||
|     bool operator<( shared_count const & r ) const noexcept | ||||
|     { | ||||
|         return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||
|     } | ||||
|  | ||||
|     std::size_t hash_value() const noexcept | ||||
|     { | ||||
|         return sp_hash_pointer( pi_ ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) | ||||
| { | ||||
|     if( pi_ == 0 || !pi_->add_ref_lock() ) | ||||
|     { | ||||
|         boost::throw_exception( boost::bad_weak_ptr() ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) noexcept: pi_( r.pi_ ) | ||||
| { | ||||
|     if( pi_ != 0 && !pi_->add_ref_lock() ) | ||||
|     { | ||||
|         pi_ = 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline bool shared_count::operator==( weak_count const & r ) const noexcept | ||||
| { | ||||
|     return pi_ == r.pi_; | ||||
| } | ||||
|  | ||||
| inline bool shared_count::operator<( weak_count const & r ) const noexcept | ||||
| { | ||||
|     return std::less<sp_counted_base *>()( pi_, r.pi_ ); | ||||
| } | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #if defined( BOOST_SP_DISABLE_DEPRECATED ) | ||||
| #pragma GCC diagnostic pop | ||||
| #endif | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED | ||||
							
								
								
									
										76
									
								
								include/boost/smart_ptr/detail/sp_convertible.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								include/boost/smart_ptr/detail/sp_convertible.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| //  detail/sp_convertible.hpp | ||||
| // | ||||
| //  Copyright 2008 Peter Dimov | ||||
| // | ||||
| //  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 | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <cstddef> | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template< class Y, class T > struct sp_convertible | ||||
| { | ||||
|     typedef char (&yes) [1]; | ||||
|     typedef char (&no)  [2]; | ||||
|  | ||||
|     static yes f( T* ); | ||||
|     static no  f( ... ); | ||||
|  | ||||
|     enum _vt { value = sizeof( (f)( static_cast<Y*>(0) ) ) == sizeof(yes) }; | ||||
| }; | ||||
|  | ||||
| template< class Y, class T > struct sp_convertible< Y, T[] > | ||||
| { | ||||
|     enum _vt { value = false }; | ||||
| }; | ||||
|  | ||||
| template< class Y, class T > struct sp_convertible< Y[], T[] > | ||||
| { | ||||
|     enum _vt { value = sp_convertible< Y[1], T[1] >::value }; | ||||
| }; | ||||
|  | ||||
| template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] > | ||||
| { | ||||
|     enum _vt { value = sp_convertible< Y[1], T[1] >::value }; | ||||
| }; | ||||
|  | ||||
| struct sp_empty | ||||
| { | ||||
| }; | ||||
|  | ||||
| template< bool > struct sp_enable_if_convertible_impl; | ||||
|  | ||||
| template<> struct sp_enable_if_convertible_impl<true> | ||||
| { | ||||
|     typedef sp_empty type; | ||||
| }; | ||||
|  | ||||
| template<> struct sp_enable_if_convertible_impl<false> | ||||
| { | ||||
| }; | ||||
|  | ||||
| template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value > | ||||
| { | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED | ||||
							
								
								
									
										93
									
								
								include/boost/smart_ptr/detail/sp_counted_base.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								include/boost/smart_ptr/detail/sp_counted_base.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  detail/sp_counted_base.hpp | ||||
| // | ||||
| //  Copyright 2005-2013 Peter Dimov | ||||
| // | ||||
| // 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) | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp> | ||||
| #include <boost/smart_ptr/detail/deprecated_macros.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if defined( BOOST_SP_DISABLE_THREADS ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_STD_ATOMIC ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_SPINLOCK ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_spin.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_USE_PTHREADS ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_pt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_nt.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_HAS_GCC_INTRINSICS ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_gcc_atomic.hpp> | ||||
|  | ||||
| #elif !defined( BOOST_NO_CXX11_HDR_ATOMIC ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp> | ||||
|  | ||||
| #elif defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_sync.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp> | ||||
|  | ||||
| #elif defined( BOOST_SP_HAS_SYNC_INTRINSICS ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_sync.hpp> | ||||
|  | ||||
| #elif defined( __SNC__ ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp> | ||||
|  | ||||
| #elif defined(__HP_aCC) && defined(__ia64) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER ) && !defined(__PATHSCALE__) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp> | ||||
|  | ||||
| #elif defined( __IBMCPP__ ) && defined( __powerpc ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp> | ||||
|  | ||||
| #elif defined( __MWERKS__ ) && defined( __POWERPC__ ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp> | ||||
|  | ||||
| #elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) && !defined( __mips16 ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp> | ||||
|  | ||||
| #elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp> | ||||
|  | ||||
| #elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_w32.hpp> | ||||
|  | ||||
| #elif defined( _AIX ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_aix.hpp> | ||||
|  | ||||
| #elif !defined( BOOST_HAS_THREADS ) | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_nt.hpp> | ||||
|  | ||||
| #else | ||||
| # include <boost/smart_ptr/detail/sp_counted_base_spin.hpp> | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED | ||||
							
								
								
									
										163
									
								
								include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								include/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,163 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64 | ||||
| // | ||||
| //  Copyright 2007 Baruch Zilber | ||||
| //  Copyright 2007 Boris Gubenko | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| // | ||||
| //  Lock-free algorithm by Alexander Terekhov | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/detail/sp_typeinfo_.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_obsolete.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <machine/sys/inline.h> | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using HP aCC++/HP-UX/IA64 sp_counted_base") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| BOOST_SP_OBSOLETE() | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| inline void atomic_increment( int * pw ) | ||||
| { | ||||
|     // ++*pw; | ||||
|  | ||||
|     _Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE); | ||||
| }  | ||||
|  | ||||
| inline int atomic_decrement( int * pw ) | ||||
| { | ||||
|     // return --*pw; | ||||
|  | ||||
|     int r = static_cast<int>(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE)); | ||||
|     if (1 == r) | ||||
|     { | ||||
|         _Asm_mf(); | ||||
|     } | ||||
|      | ||||
|     return r - 1; | ||||
| } | ||||
|  | ||||
| inline int atomic_conditional_increment( int * pw ) | ||||
| { | ||||
|     // if( *pw != 0 ) ++*pw; | ||||
|     // return *pw; | ||||
|  | ||||
|     int v = *pw; | ||||
|      | ||||
|     for (;;) | ||||
|     { | ||||
|         if (0 == v) | ||||
|         { | ||||
|             return 0; | ||||
|         } | ||||
|          | ||||
|         _Asm_mov_to_ar(_AREG_CCV, | ||||
|                        v, | ||||
|                        (_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE)); | ||||
|         int r = static_cast<int>(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE)); | ||||
|         if (r == v) | ||||
|         { | ||||
|             return r + 1; | ||||
|         } | ||||
|          | ||||
|         v = r; | ||||
|     } | ||||
| } | ||||
|  | ||||
| class BOOST_SYMBOL_VISIBLE sp_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base( sp_counted_base const & ); | ||||
|     sp_counted_base & operator= ( sp_counted_base const & ); | ||||
|  | ||||
|     int use_count_;        // #shared | ||||
|     int weak_count_;       // #weak + (#shared != 0) | ||||
|  | ||||
| public: | ||||
|  | ||||
|     sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     virtual ~sp_counted_base() // nothrow | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     // dispose() is called when use_count_ drops to zero, to release | ||||
|     // the resources managed by *this. | ||||
|  | ||||
|     virtual void dispose() = 0; // nothrow | ||||
|  | ||||
|     // destroy() is called when weak_count_ drops to zero. | ||||
|  | ||||
|     virtual void destroy() // nothrow | ||||
|     { | ||||
|         delete this; | ||||
|     } | ||||
|  | ||||
|     virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; | ||||
|     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; | ||||
|     virtual void * get_untyped_deleter() = 0; | ||||
|  | ||||
|     void add_ref_copy() | ||||
|     { | ||||
|         atomic_increment( &use_count_ ); | ||||
|     } | ||||
|  | ||||
|     bool add_ref_lock() // true on success | ||||
|     { | ||||
|         return atomic_conditional_increment( &use_count_ ) != 0; | ||||
|     } | ||||
|  | ||||
|     void release() // nothrow | ||||
|     { | ||||
|         if( atomic_decrement( &use_count_ ) == 0 ) | ||||
|         { | ||||
|             dispose(); | ||||
|             weak_release(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void weak_add_ref() // nothrow | ||||
|     { | ||||
|         atomic_increment( &weak_count_ ); | ||||
|     } | ||||
|  | ||||
|     void weak_release() // nothrow | ||||
|     { | ||||
|         if( atomic_decrement( &weak_count_ ) == 0 ) | ||||
|         { | ||||
|             destroy(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     long use_count() const // nothrow | ||||
|     { | ||||
|         return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED | ||||
							
								
								
									
										152
									
								
								include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								include/boost/smart_ptr/detail/sp_counted_base_aix.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED | ||||
|  | ||||
| // | ||||
| //  detail/sp_counted_base_aix.hpp | ||||
| //   based on: detail/sp_counted_base_w32.hpp | ||||
| // | ||||
| //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. | ||||
| //  Copyright 2004-2005 Peter Dimov | ||||
| //  Copyright 2006 Michael van der Westhuizen | ||||
| // | ||||
| //  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) | ||||
| // | ||||
| // | ||||
| //  Lock-free algorithm by Alexander Terekhov | ||||
| // | ||||
| //  Thanks to Ben Hitchings for the #weak + (#shared != 0) | ||||
| //  formulation | ||||
| // | ||||
|  | ||||
| #include <boost/smart_ptr/detail/sp_typeinfo_.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <builtins.h> | ||||
| #include <sys/atomic_op.h> | ||||
|  | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
|  | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using AIX sp_counted_base") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| inline void atomic_increment( int32_t* pw ) | ||||
| { | ||||
|     // ++*pw; | ||||
|  | ||||
|     fetch_and_add( pw, 1 ); | ||||
| } | ||||
|  | ||||
| inline int32_t atomic_decrement( int32_t * pw ) | ||||
| { | ||||
|     // return --*pw; | ||||
|  | ||||
|     int32_t originalValue; | ||||
|  | ||||
|     __lwsync(); | ||||
|     originalValue = fetch_and_add( pw, -1 ); | ||||
|     __isync(); | ||||
|  | ||||
|     return (originalValue - 1); | ||||
| } | ||||
|  | ||||
| inline int32_t atomic_conditional_increment( int32_t * pw ) | ||||
| { | ||||
|     // if( *pw != 0 ) ++*pw; | ||||
|     // return *pw; | ||||
|  | ||||
|     int32_t tmp = fetch_and_add( pw, 0 ); | ||||
|     for( ;; ) | ||||
|     { | ||||
|         if( tmp == 0 ) return 0; | ||||
|         if( compare_and_swap( pw, &tmp, tmp + 1 ) ) return (tmp + 1); | ||||
|     } | ||||
| } | ||||
|  | ||||
| class BOOST_SYMBOL_VISIBLE sp_counted_base | ||||
| { | ||||
| private: | ||||
|  | ||||
|     sp_counted_base( sp_counted_base const & ); | ||||
|     sp_counted_base & operator= ( sp_counted_base const & ); | ||||
|  | ||||
|     int32_t use_count_;        // #shared | ||||
|     int32_t weak_count_;       // #weak + (#shared != 0) | ||||
|  | ||||
| public: | ||||
|  | ||||
|     sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     virtual ~sp_counted_base() // nothrow | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     // dispose() is called when use_count_ drops to zero, to release | ||||
|     // the resources managed by *this. | ||||
|  | ||||
|     virtual void dispose() = 0; // nothrow | ||||
|  | ||||
|     // destroy() is called when weak_count_ drops to zero. | ||||
|  | ||||
|     virtual void destroy() // nothrow | ||||
|     { | ||||
|         delete this; | ||||
|     } | ||||
|  | ||||
|     virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; | ||||
|     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; | ||||
|     virtual void * get_untyped_deleter() = 0; | ||||
|  | ||||
|     void add_ref_copy() | ||||
|     { | ||||
|         atomic_increment( &use_count_ ); | ||||
|     } | ||||
|  | ||||
|     bool add_ref_lock() // true on success | ||||
|     { | ||||
|         return atomic_conditional_increment( &use_count_ ) != 0; | ||||
|     } | ||||
|  | ||||
|     void release() // nothrow | ||||
|     { | ||||
|         if( atomic_decrement( &use_count_ ) == 0 ) | ||||
|         { | ||||
|             dispose(); | ||||
|             weak_release(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void weak_add_ref() // nothrow | ||||
|     { | ||||
|         atomic_increment( &weak_count_ ); | ||||
|     } | ||||
|  | ||||
|     void weak_release() // nothrow | ||||
|     { | ||||
|         if( atomic_decrement( &weak_count_ ) == 0 ) | ||||
|         { | ||||
|             destroy(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     long use_count() const // nothrow | ||||
|     { | ||||
|         return fetch_and_add( const_cast<int32_t*>(&use_count_), 0 ); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_AIX_HPP_INCLUDED | ||||
| @@ -1,5 +1,5 @@ | ||||
| #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED | ||||
| #define BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED | ||||
| 
 | ||||
| // MS compatible compilers support #pragma once
 | ||||
| 
 | ||||
| @@ -24,7 +24,16 @@ | ||||
| //  formulation
 | ||||
| //
 | ||||
| 
 | ||||
| #include <typeinfo> | ||||
| #include <boost/smart_ptr/detail/sp_typeinfo_.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_obsolete.hpp> | ||||
| #include <boost/config.hpp> | ||||
| 
 | ||||
| #if defined(BOOST_SP_REPORT_IMPLEMENTATION) | ||||
| 
 | ||||
| #include <boost/config/pragma_message.hpp> | ||||
| BOOST_PRAGMA_MESSAGE("Using CodeWarrior/PowerPC sp_counted_base") | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| namespace boost | ||||
| { | ||||
| @@ -53,7 +62,11 @@ inline long atomic_decrement( register long * pw ) | ||||
| 
 | ||||
|     asm | ||||
|     { | ||||
| #if defined(__PPCZen__) || defined(__PPCe500__) || defined(__PPCe500v2__) | ||||
|     msync | ||||
| #else | ||||
|     sync | ||||
| #endif | ||||
| 
 | ||||
| loop: | ||||
| 
 | ||||
| @@ -91,7 +104,7 @@ store: | ||||
|     return a; | ||||
| } | ||||
| 
 | ||||
| class sp_counted_base | ||||
| class BOOST_SYMBOL_VISIBLE sp_counted_base | ||||
| { | ||||
| private: | ||||
| 
 | ||||
| @@ -123,7 +136,9 @@ public: | ||||
|         delete this; | ||||
|     } | ||||
| 
 | ||||
|     virtual void * get_deleter( std::type_info const & ti ) = 0; | ||||
|     virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0; | ||||
|     virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0; | ||||
|     virtual void * get_untyped_deleter() = 0; | ||||
| 
 | ||||
|     void add_ref_copy() | ||||
|     { | ||||
| @@ -167,4 +182,4 @@ public: | ||||
| 
 | ||||
| } // namespace boost
 | ||||
| 
 | ||||
| #endif  // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
 | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
 | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user